折叠,功能构成,单子和懒惰,哦,我的?

Dan*_*ton 22 monads haskell fold function-composition

我很困惑.我可以这样写:

import Control.Monad

main = print $ head $ (foldr (.) id [f, g]) [3]
  where f = (1:)
        g = undefined
Run Code Online (Sandbox Code Playgroud)

而输出是1.这是有道理的,因为它减少到:

main = print $ head $ ((1:) . undefined . id) [3]
main = print $ head $ (1:) ((undefined . id) [3])
main = print $ head $ 1 : ((undefined . id) [3])
main = print $ 1
Run Code Online (Sandbox Code Playgroud)

但是,如果我使用模糊相似的monadic技术,它不会起作用:

import Control.Monad

main = print $ (foldr (<=<) return [f, g]) 3
  where f = const Nothing
        g = undefined
Run Code Online (Sandbox Code Playgroud)

这点击prelude.Undefined.这很奇怪,因为我希望它减少:

main = print $ ((const Nothing) <=< undefined <=< return) 3
main = print $ return 3 >>= undefined >>= (\_ -> Nothing)
main = print $ Nothing -- nope! instead, undefined makes this blow up
Run Code Online (Sandbox Code Playgroud)

但是,翻转组成的顺序:

import Control.Monad

main = print $ (foldr (>=>) return [f, g]) 3
  where f = const Nothing
        g = undefined
Run Code Online (Sandbox Code Playgroud)

确实完成了预期的短路并产生Nothing.

main = print $ (const Nothing >=> undefined >=> return) 3
main = print $ (const Nothing 3) >>= undefined >>= return
main = print $ Nothing >>= undefined >>= return
main = print $ Nothing
Run Code Online (Sandbox Code Playgroud)

我想比较两种方法可能比较苹果和橙子,但你能解释一下这种差异吗?我认为这f <=< g是monadic类似物f . g,但它们显然不像我想象的那样类似.你能解释一下原因吗?

ham*_*mar 20

这取决于您正在使用哪个monad,以及如何(>>=)定义其运算符.

在的情况下Maybe,(>>=)是在它的第一个参数严格,如丹尼尔费说明.

以下是一些其他monad的一些结果.

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

身份:懒惰.

> Control.Monad.Identity.runIdentity foo
42
Run Code Online (Sandbox Code Playgroud)

IO:严格.

> foo :: IO Integer
*** Exception: Prelude.undefined
Run Code Online (Sandbox Code Playgroud)

读者:懒惰.

> Control.Monad.Reader.runReader foo "bar"
42
Run Code Online (Sandbox Code Playgroud)

作家:既有懒惰又有严格的变体.

> Control.Monad.Writer.runWriter foo
(42,())
> Control.Monad.Writer.Strict.runWriter foo
*** Exception: Prelude.undefined
Run Code Online (Sandbox Code Playgroud)

州:既有严格也有懒惰版本.

> Control.Monad.State.runState foo "bar"
(42,"*** Exception: Prelude.undefined
> Control.Monad.State.Strict.runState foo "bar"
*** Exception: Prelude.undefined
Run Code Online (Sandbox Code Playgroud)

Cont:严格.

> Control.Monad.Cont.runCont foo id
*** Exception: Prelude.undefined
Run Code Online (Sandbox Code Playgroud)


Dan*_*her 19

Maybe一个参数中的绑定是严格的.

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

所以,当你尝试

Just v >>= undefined >>= \_ -> Nothing
Run Code Online (Sandbox Code Playgroud)

你打了

undefined v >>= \_ -> Nothing
Run Code Online (Sandbox Code Playgroud)

并且实现需要找出是否undefined vNothingJust something要查看使用哪个等式(>>=).

另一方面,

Nothing >>= undefined
Run Code Online (Sandbox Code Playgroud)

确定结果而不查看第二个参数(>>=).