Folding, function composition, monads, and laziness, oh my?

后端 未结 2 1389
[愿得一人]
[愿得一人] 2020-12-29 23:06

I am puzzled. I can write this:

import Control.Monad

main = print $ head $ (foldr (.) id [f, g]) [3]
  where f = (1:)
        g = undefined
<
相关标签:
2条回答
  • 2020-12-29 23:58

    It depends on which monad you're working with, and how its (>>=) operator is defined.

    In the case of Maybe, (>>=) is strict in its first argument, as Daniel Fischer explained.

    Here are some results for a handful of other monads.

    > :set -XNoMonomorphismRestriction
    > let foo = (const (return 42) <=< undefined <=< return) 3
    > :t foo
    foo :: (Num t, Monad m) => m t
    

    Identity: Lazy.

    > Control.Monad.Identity.runIdentity foo
    42
    

    IO: Strict.

    > foo :: IO Integer
    *** Exception: Prelude.undefined
    

    Reader: Lazy.

    > Control.Monad.Reader.runReader foo "bar"
    42
    

    Writer: Has both a lazy and a strict variant.

    > Control.Monad.Writer.runWriter foo
    (42,())
    > Control.Monad.Writer.Strict.runWriter foo
    *** Exception: Prelude.undefined
    

    State: Has also both a strict and a lazy version.

    > Control.Monad.State.runState foo "bar"
    (42,"*** Exception: Prelude.undefined
    > Control.Monad.State.Strict.runState foo "bar"
    *** Exception: Prelude.undefined
    

    Cont: Strict.

    > Control.Monad.Cont.runCont foo id
    *** Exception: Prelude.undefined
    
    0 讨论(0)
  • 2020-12-30 00:03

    The bind for Maybe is strict in the first argument.

    Just v >>= f = f v
    Nothing >>= f = Nothing
    

    So when you try

    Just v >>= undefined >>= \_ -> Nothing
    

    you hit

    undefined v >>= \_ -> Nothing
    

    and the implementation needs to find out whether undefined v is Nothing or Just something to see which equation of (>>=) to use.

    On the other hand,

    Nothing >>= undefined
    

    determines the result without looking at the second argument of (>>=).

    0 讨论(0)
提交回复
热议问题