XrX*_*rXr 1 monads haskell do-notation
我正在阅读https://wiki.haskell.org/Do_notation_considered_harmful并惊讶于阅读以下内容
新手可能会认为陈述的顺序决定了执行的顺序.......陈述的顺序也不是评估顺序的标准.
维基文章给出了一些展示这个属性的例子.虽然这些例子很有意义,但我仍然不完全相信这个陈述是正确的,因为如果我写的是这样的话
main = do
putStrLn "foo"
putStrLn "bar"
putStrLn "baz"
Run Code Online (Sandbox Code Playgroud)
这三行按照陈述的顺序排列.那到底是怎么回事?
它所说的是,陈述的顺序不会影响评估标准.正如@chi指出的那样,IO monad效应按顺序排序,但它们的评估顺序仍然未知.monad的一个例子,它将使概念清晰:
test = do
x <- Just (2 + undefined)
y <- Nothing
return (x + y)
Run Code Online (Sandbox Code Playgroud)
在ghci:
?> test
Nothing
Run Code Online (Sandbox Code Playgroud)
上面的代码有三个陈述.它可以脱糖成下列形式:
Just (2 + undefined) >>= \x -> Nothing >>= \y -> return (x + y)
Run Code Online (Sandbox Code Playgroud)
既然(>>=)是左关联的,它将被评估为:
(Just (2 + undefined) >>= \x -> Nothing) >>= \y -> return (x + y)
请注意,Maybemonad的定义如下:
(>>=) :: Maybe a -> (a -> Maybe b) -> Maybe b
Nothing >>= _ = Nothing -- A failed computation returns Nothing
(Just x) >>= f = f x -- Applies function f to value x
Run Code Online (Sandbox Code Playgroud)
将值(2 + undefined)应用于该函数\x -> Nothing将导致Nothing.2 + undefined由于Haskell遵循惰性评估策略,表达式未被评估.
现在我们有一个缩小的形式:
Nothing >>= \y -> return (2 + undefined + y)
Run Code Online (Sandbox Code Playgroud)
Monad查看它的实例,你可以看到这将产生Nothing因为Nothing >>= _ = Nothing.如果争论是严格的,那该怎么办:
test = do
!x <- Just (2 + undefined)
y <- Nothing
return (y + x)
Run Code Online (Sandbox Code Playgroud)
演示ghci:
?> test
*** Exception: Prelude.undefined
Run Code Online (Sandbox Code Playgroud)
如果我们遵循严格的评估程序,那么您可以看到订单确实很重要.但在懒惰的环境中,陈述的顺序无关紧要.因此维基声称,"声明的顺序不是评估顺序的标准".