Gesh gesh at gesh.uni.cx
Sun Apr 6 09:47:54 UTC 2014

```On April 6, 2014 10:41:41 AM GMT+03:00, "John M. Dlugosz" <ngnr63q02 at sneakemail.com> wrote:
>A spiral approach to learning: you understand, then you learn more, and
>then you are more
>confused than ever.
>
Excellent characterization of learning. Mind if I use it?
>I recall that a function in the IO Monad just combines actions to make
>a big action list,
>and doesn't actually do the side-effect-laden "work" until it is later
>triggered, normally
>because the program is defined to evaluate main.
>
>Depending on the time of day and which example I pick, I can sometimes
>"really happening" in the definition of >>=.  But here are some
>specific questions:
>
>
>> What is a for-each loop really? It's something which performs some
>action based on each
>> element of a list. So we might imagine a function with the type:
>>
>> forM :: (Monad m) => [a] -> (a -> m b) -> m [b]
>>
>> (as an added bonus, we'll have it collect the results of each
>iteration).
>>
>> We can write this with sequence and map:
>>
>> forM xs f = sequence (map f xs)
>>
>> we apply the function to each element of the list to construct the
>action for that
>> iteration, and then sequence the actions together into a single
>computation.
>>
>
>So map by itself produces a [m b].  Why does it need to be turned into
>m [b]?  What does
>the 'sequence' accomplish, other than restructuring the results that
>
In essence, what a value of type Monad m => [m a] means is that you have a list full of monadic actions. It's a bit like having a list of functions - while you can certainly use the actions and functions, respectively, they haven't been evaluated *yet*. Whereas a value of type Monad m => m [a] represents a monadic action returning some list of values. Thus, sequence is collecting the values computed by each action. This is all made clear by the implementation of sequence:
sequence ms = foldr k (return []) ms
where k m m' = do { x <- m; xs <- m'; return (x:xs) }
Note that lists aren't special, Data.Traversable defines sequence for all traversable values:
>The reason I asked about (#⋯#) is because I wanted to see what IO was
>really doing, to see
>what the difference was between using >>= initially and then somehow
>"cranking" it later.
>
>lists
>>     {-# INLINE return #-}
>>     {-# INLINE (>>)   #-}
>>     {-# INLINE (>>=)  #-}
>>     m >> k    = m >>= \ _ -> k
>>     return    = returnIO
>>     (>>=)     = bindIO
>>     fail s    = failIO s
>>
>> returnIO :: a -> IO a
>> returnIO x = IO \$ \ s -> (# s, x #)
>>
>> bindIO :: IO a -> (a -> IO b) -> IO b
>> bindIO (IO m) k = IO \$ \ s -> case m s of (# new_s, a #) -> unIO (k
>a) new_s
>>
>> thenIO :: IO a -> IO b -> IO b
>> thenIO (IO m) k = IO \$ \ s -> case m s of (# new_s, _ #) -> unIO k
>new_s
>>
>> unIO :: IO a -> (State# RealWorld -> (# State# RealWorld, a #))
>> unIO (IO a) = a
>
>where bindIO is the function of interest.  In a chain of commands,
>getLine might be the
>'k' argument to bindIO.  Somewhere there's a real machine function
>called to do the