簡體   English   中英

折疊,功能構成,單子和懶惰,哦,我的?

[英]Folding, function composition, monads, and laziness, oh my?

我很困惑。 我可以這樣寫:

import Control.Monad

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

輸出為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

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

import Control.Monad

main = print $ (foldr (<=<) return [f, g]) 3
  where f = const Nothing
        g = undefined

這打到了prelude.Undefinedprelude.Undefined 這很奇怪,因為我希望它減少:

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

但是,翻轉組成的順序:

import Control.Monad

main = print $ (foldr (>=>) return [f, g]) 3
  where f = const Nothing
        g = undefined

確實完成了預期的短路並且Nothing產生Nothing

main = print $ (const Nothing >=> undefined >=> return) 3
main = print $ (const Nothing 3) >>= undefined >>= return
main = print $ Nothing >>= undefined >>= return
main = print $ Nothing

我想比較兩種方法可能比較蘋果和橙子,但你能解釋一下這種差異嗎? 我認為f <=< gf . g的monadic類似物f . g f . g ,但它們顯然不像我想象的那樣類似。 你能解釋一下原因嗎?

這取決於您正在使用哪個monad,以及如何定義其(>>=)運算符。

Maybe的情況下, (>>=)在其第一個參數中是嚴格的,正如Daniel Fischer解釋的那樣。

以下是一些其他monad的一些結果。

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

身份:懶惰。

> Control.Monad.Identity.runIdentity foo
42

IO:嚴格。

> foo :: IO Integer
*** Exception: Prelude.undefined

讀者:懶惰。

> Control.Monad.Reader.runReader foo "bar"
42

作家:既有懶惰又有嚴格的變體。

> Control.Monad.Writer.runWriter foo
(42,())
> Control.Monad.Writer.Strict.runWriter foo
*** Exception: Prelude.undefined

州:既有嚴格也有懶惰版本。

> Control.Monad.State.runState foo "bar"
(42,"*** Exception: Prelude.undefined
> Control.Monad.State.Strict.runState foo "bar"
*** Exception: Prelude.undefined

Cont:嚴格。

> Control.Monad.Cont.runCont foo id
*** Exception: Prelude.undefined

對於Maybe的綁定在第一個參數中是嚴格的。

Just v >>= f = f v
Nothing >>= f = Nothing

所以,當你嘗試

Just v >>= undefined >>= \_ -> Nothing

你打了

undefined v >>= \_ -> Nothing

並且實現需要找出undefined vNothing還是Just something要查看要使用哪個(>>=)等式。

另一方面,

Nothing >>= undefined

確定結果而不查看(>>=)的第二個參數。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM