我正在阅读https://wiki.haskell.org/Do_notation_considered_harmful并惊讶于阅读以下内容
新手可能会认为陈述的顺序决定了执行的顺序。 ......陈述的顺序也不是评估顺序的标准。
wiki帖子提供了一些演示此属性的示例。虽然这些例子是有道理的,但我仍然不完全相信这句话是真的,因为如果我写的话就像
main = do
putStrLn "foo"
putStrLn "bar"
putStrLn "baz"
这三行按照陈述的顺序排列。那究竟发生了什么?
答案 0 :(得分:6)
它所说的是陈述的顺序不会影响评估标准。正如@chi指出的那样,IO monad效应按顺序排序,但它们的评估顺序仍然未知。 monad的一个例子,它将使概念清晰:
test = do
x <- Just (2 + undefined)
y <- Nothing
return (x + y)
在ghci:
λ> test
Nothing
上面的代码有三个陈述。它可以脱糖成下列形式:
Just (2 + undefined) >>= \x -> Nothing >>= \y -> return (x + y)
现在,由于(>>=)
是关联的,因此将按如下方式进行评估:
(Just (2 + undefined) >>= \x -> Nothing) >>= \y -> return (x + y)
请注意,Maybe
monad的定义如下:
(>>=) :: 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
将值(2 + undefined)
应用于函数\x -> Nothing
将导致Nothing
。
表达式2 + undefined
未经评估,这要归功于Haskell遵循的惰性评估策略。
现在我们有一个简化形式:
Nothing >>= \y -> return (2 + undefined + y)
查看Monad
实例,您可以看到这会生成Nothing
因为Nothing >>= _ = Nothing
。
如果争论是严格的,那该怎么办:
test = do
!x <- Just (2 + undefined)
y <- Nothing
return (y + x)
ghci
演示:
λ> test
*** Exception: Prelude.undefined
如果我们遵循严格的评估程序,那么您可以看到订单确实很重要。但在懒惰的环境中,陈述的顺序并不重要。因此维基声称,&#34;陈述的顺序不是评估顺序的标准&#34;。