【问题标题】:When do [do x] and [do return x] evaluate differently?[do x] 和 [do return x] 何时评估不同?
【发布时间】:2016-09-26 10:08:33
【问题描述】:
*Main> do 0

0

*Main> do return 0

0

*Main> do (Just 0)

只有0

*Main> do return (Just 0)

只有0

*Main> do Nothing

什么都没有

*Main> do return Nothing

什么都没有

bareDo :: a -> a
bareDo x = do x

doReturn :: Monad m => a -> m a
doReturn x = do return x

为什么do xdo return x 会评估相同的值,什么时候不会?

我正在尝试理解Monad,教程已经足够了,discussion 在那里但我无法理解。

这甚至是post 写作

不要阅读 monad 教程。

所以,我想弄脏我的手可能会有所帮助。

我非常感谢帮助我离开这里的人(我的意思是 doreturn,而不是 Monad。我知道这需要几天时间)。

【问题讨论】:

标签: haskell monads


【解决方案1】:

do 在单个表达式上一无所获:它只是一个句法先驱,表明您可以在此处使用动作排序(这将需要一个单子),但如果您不这样做那么它与将表达式包装在冗余括号层中的效果相同。

所以你的示例会话等同于:

Prelude> 0
0
Prelude> return 0
0
Prelude> Just 0
Just 0
Prelude> return (Just 0)
Just 0
Prelude> Nothing
Nothing
Prelude> return Nothing
Nothing

现在的问题是为什么return 在这里没有完成任何事情。好吧,实际上确实如此,只是您看不到它,因为 GHCi 隐藏了实现细节。 GHCi 有两种完全不同的交互评估模式:

  1. IO 动作被执行,然后结果printed。
  2. 其他一切都是printed。

至关重要的是,GHCi 在继续执行 2 之前会非常努力地将所有内容解释为 IO 操作。因此,如果您给它一个像 return 0 这样的模棱两可的表达式,它会注意到一个可能的实例化是 IO Integer。它立即默认为执行此无副作用操作,因此您在结果中看到的所有内容都是0。不过,这只发生在 IO 上,不会发生在任何其他单子上:

Prelude> return 0 :: IO Integer
0
Prelude> return 0 :: Maybe Integer
Just 0
Prelude> return 0 :: [] Integer
[0]

当 monad 不明确时,GHCi 恰好默认为 IO,但在 Haskell 中则不会发生这种情况。

【讨论】:

    【解决方案2】:

    好的答案:从来没有,因为return :: Monad m => a -> m a 将一个对象放入一个盒子中。

    正确,但无法使用的答案:当 x 是给定 monad 的 return 的固定点时。

    【讨论】:

    • 严格来说这是对相反的答案:“什么时候..和..评估相同?”
    猜你喜欢
    • 1970-01-01
    • 2012-12-09
    • 1970-01-01
    • 2018-06-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-15
    • 1970-01-01
    相关资源
    最近更新 更多