Is Haskell's mapM not lazy?

前端 未结 5 791
情歌与酒
情歌与酒 2020-12-01 23:36

UPDATE: Okay this question becomes potentially very straightforward.

q <- mapM return [1..]

Why does this never return

5条回答
  •  北荒
    北荒 (楼主)
    2020-12-02 00:12

    This question is showing very well the difference between the IO Monad and other Monads. In the background the mapM builds an expression with a bind operation (>>=) between all the list elements to turn the list of monadic expressions into a monadic expression of a list. Now, what is different in the IO monad is that the execution model of Haskell is executing expressions during the bind in the IO Monad. This is exactly what finally forces (in a purely lazy world) something to be executed at all.

    So IO Monad is special in a way, it is using the sequence paradigm of bind to actually enforce execution of each step and this is what our program makes to execute anything at all in the end. Others Monads are different. They have other meanings of the bind operator, depending on the Monad. IO is actually the one Monad which execute things in the bind and this is the reason why IO types are "actions".

    The following example show that other Monads do not enforce execution, the Maybe monad for example. Finally this leds to the result that a mapM in the IO Monad returns an expression, which - when executed - executes each single element before returning the final value.

    There are nice papers about this, start here or search for denotational semantics and Monads: Tackling the awkward squad: http://research.microsoft.com/en-us/um/people/simonpj/papers/marktoberdorf/mark.pdf

    Example with Maybe Monad:

    module Main where

    fstMaybe :: [Int] -> Maybe [Int] fstMaybe = mapM (\x -> if x == 3 then Nothing else Just x)

    main = do let r = fstMaybe [1..] return r

提交回复
热议问题