
On Sat, Feb 10, 2018 at 02:48:07PM +0000, Olumide wrote:
I find the following implementation of join in the text is hard to understand or apply
join :: (Monad m) => m (m a) -> m a join mm = do m <- mm m
Hello Olumide, remember that: join :: (Monad m) => m (m a) -> m a join mm = do m <- mm m is the same as: join :: (Monad m) => m (m a) -> m a join mm = mm >>= \m -> m In general remember that when you have a "plain" value, the last line of a monadic expression is often: return someSimpleVal So: monadicexpr = do x <- [4] return x -- can't just write `x` When you have a monad inside a monad, you can just "peel" the outer layer and live happily thereafter: monadicexpr = do x <- [[4]] x -- result will be: [4], no need to use return -- because [4] (and not 4) is still a -- list monad As for State, remember that State is: data State s a = State $ s -> (a, s) -- almost So a function that from a state s, calculates a new state s' and returns a value of type `a`. When we use the bind operator in a do block, it's like we're extracting that value of type `a` monadicexpr = do x <- someState return x -- again we need to wrap this value -- before returning it, this state being -- -- \s -> (x, s) -- -- i.e. we do nothing to the parameter state -- and place `x` as a result. -- Same trick there, if `x` is actually a State-inside-State (e.g. of type `State s (State s a)`), there is no need for wrapping anymore. Does this make sense? -F