【问题标题】:Folding, function composition, monads, and laziness, oh my?折叠、函数组合、单子和惰性,哦,天哪?
【发布时间】:2012-01-05 04:53:14
【问题描述】:

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

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

但如果我使用一种类似的单子技术,它的工作原理就不一样了:

import Control.Monad

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

点击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

但是,颠倒构图的顺序:

import Control.Monad

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

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

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

我想比较这两种方法可能是比较苹果和橙子,但你能解释一下区别吗?我认为f &lt;=&lt; gf . g 的一元类比,但它们显然不像我想象的那样相似。你能解释一下原因吗?

【问题讨论】:

    标签: haskell monads fold function-composition


    【解决方案1】:

    这取决于您使用的是哪个 monad,以及它的 (&gt;&gt;=) 运算符是如何定义的。

    Maybe 的情况下,(&gt;&gt;=) 在其第一个参数中是严格的,正如 Daniel Fischer 解释的那样。

    以下是一些其他单子的一些结果。

    > :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
    

    续:严格。

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

    【讨论】:

      【解决方案2】:

      Maybe 的绑定在第一个参数中是严格的。

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

      所以当你尝试

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

      你打了

      undefined v >>= \_ -> Nothing
      

      并且实现需要找出undefined vNothing 还是Just something 以查看使用(&gt;&gt;=) 的哪个等式。

      另一方面,

      Nothing >>= undefined
      

      在不查看(&gt;&gt;=) 的第二个参数的情况下确定结果。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-01-12
        • 1970-01-01
        • 2011-01-15
        • 2013-01-11
        • 2012-04-27
        • 1970-01-01
        • 2012-02-20
        相关资源
        最近更新 更多