15.11.14

A very easy/hard haskell puzzle.

credit: (all screenshots are either from haskell.org, typeclassopedia, or wikibooks.org)

Today while attempting to monadicize a haskell project, I ran into the following error message.


The solution would be easy enough to hack around on.  But instead, I figured it might be worthwhile to take the time to figure out what an [IO String] type actually represents.

For that matter, understanding the IO type, in haskell.

The error sprung from this line of code.

There are multiple problems with this line :) .  Focus on, for now, the fact that readMay won't compile against getLine.  But why ? 

my assumption was that the readMay function would be able to process the output of "getLine", which reads a String (presumably).

So, to solve the problem, we can take a look at the getLine function's definition.

So, this function takes "IO" as input, and returns a string.  

But what is IO, really?  Its many things.
For now, we should note that its a functor.  

So, since IO is a functor.  That means if

  1. I give it a function, which transforms, say, a "string" to an "int".
  2. The functor property of IO guarantees that, when operating on an IO of type "string", it will return a new IO of type "int", given my function.
So - how does that help us ? 

Simple : Instances of the functor class can be used now in a broader context, why?  Because I am guaranteed that anything of type functor is capable of reaching inside itself, and performing an operation on its contents, and returning a new instance of itself with the contents modified.

But how do I tell the haskell compiler to carefully reach inside a monad and do an operation? 

This is done, for example, using liftM.

Here's the definition of liftM...

http://en.wikibooks.org/wiki/Haskell/Monad_transformers#liftM

So, there we have it . In summary.


  1. In idiomatic haskell, we often wrap things in boxes.  Just/Maybe is one example, IO is another, and so on.  These Monadic operators need tooling in order to operate on them.
  2. The tooling that operates on them relies on guarantees that the Monads provide - the most fundamental of which - is the functor property which monads have.
  3. Functors allow us to reach inside a wrapped type and do an operation on it, declaratively, so that we can express type safe operations in a natural and declarative way, without losing the rigor necessary for dealing with the every day chores of defensive programming.






No comments:

Post a Comment