Why will a IO nested in other monads not execute? Is there a way to force them to?

前端 未结 3 939
迷失自我
迷失自我 2021-01-19 10:19

This is a follow up of my last question. IO action nested in other monads not executing

The solution to that question was to remove some of the monads, and that all

3条回答
  •  时光说笑
    2021-01-19 11:00

    Well ... you ask the question:

    Why did I need to unnest the monads? Is there a way to execute the IO without unnesting?

    Well, let me put it as blunt as possibe: Unnesting or joining how we call it in Haskell-land, is not just yet another monad combinator, it is a holy special moand thing that differentiates Monads from Functor and Applicative!

    Yes, that totally means that the Monad type class could have been designed with a join method instead of >>=.

    Actually unnesting and binding are two different perspectives for the same thing!

    Let me spoil the rest of this post:

    join = (>>= id)                  
    

    ... and:

    (ma >>= amb) = join (amb <$> ma)
    

    Let's prove them equal by showing that we can make a join of >>= and vice versa.

    Making join from >>=

    Ok now join = (>>= id) in more detail:

    join mmx = do mx <- mmx
                  x <- mx
                  return x
    

    and then:

    join mmx = do mx <- mmx
                  mx
    

    and now with bind aka >>=:

    join mmx = mmx >>= id
    

    and point free using sections:

    join = (>>= id)
    

    Making >>= from join

    Now the other way around, it is harder, we need that fact that every Monad is a Functor too.

    Remember what >>= actaully does (pun intended):

    ma >>= amb = do a <- ma
                    amb a
    

    We know that amb is a function of type a -> m b, the idea is to use fmap which has (c -> d) -> m c -> m d, if we fmap amb we get an expression fmap amb then c becomes a and d becomes m b and m c -> m d hence becomes m a -> m (m b)!

    Now we are thrilled: m (m b) just screams join, we only need to put in the m a which we can do with normal application:

    ma >>= amb = do mb <- fmap amb ma
                    mb
    

    and this is something we saw in the previous section:

    join mmb = do mb <- mmb
                  mb
    

    with mmb == fmap amb ma

    ma >>= amb == do mb <- fmap amb ma == join (fmap amb ma)
                     mb
    

    There you go.

提交回复
热议问题