为什么haskell评估a >> b?

Eri*_*son 7 monads haskell functional-programming operators

haskell中Monads的>>运算符通常定义为

(>>) :: m a -> m b -> m b
a >> b = a >>= \_ -> b
Run Code Online (Sandbox Code Playgroud)

它可以用来打印像

main = putStr "foo" >> putStrLn "bar"
Run Code Online (Sandbox Code Playgroud)

为什么编译器不会优化价值putStr "foo"而只是评估putStrLn "bar"?它不需要它,为什么要计算呢?

Pet*_*lák 10

正如克里斯所说,这取决于monad.Identity或者Reader不会评估前面的部分>>,因为他们不需要它来计算结果.其他的单子,比如Writer,Maybe,Either,State或IO意志.

我们Maybe以此为例.>>=被定义为

Nothing  >>= _  = Nothing
(Just x) >>= f  = f x
Run Code Online (Sandbox Code Playgroud)

所以如果我们扩大,>>我们得到

Nothing  >> _  = Nothing
(Just x) >> y  = y
Run Code Online (Sandbox Code Playgroud)

因此,Maybe必须评估前面的内容>>,看看结果是否Nothing或y.

IO 故意以某种方式定义,以便评估动作是否需要其结果(否则将无法使用).


Cub*_*bic 6

咦?当然它需要的价值putStr "foo".它被评估>>=- 只有动作的结果被抛弃,而不是动作本身,如果你想将monads视为动作.

例如,在解析器中,这意味着丢弃刚刚解析的序列 - 但它仍然被解析,因此光标仍然向前移动.

  • @ErikHenriksson你混合了monadic动作`putStr"foo"`和monadic动作`putStr"foo"`产生的值.例如,`return [1 ..] >> putStrLn"Hello World"`工作正常,因为值`[1 ..]`永远不会被评估,但`return [1 ..]`是. (10认同)

Chr*_*icz 6

这取决于monad.在IO中进行评估.在Identity中,第一个未评估:

> import Control.Monad.Identity
> import Control.Monad.Trace
> let x = trace "x" $ return () :: Identity ()
> let y = trace "y" $ return () :: Identity ()
> runIdentity $ x >> y
y
()
Run Code Online (Sandbox Code Playgroud)