什么时候[do x]和[do return x]的评价方式不同?

Rah*_*ahn 5 monads haskell

*Main> do 0
Run Code Online (Sandbox Code Playgroud)

0

*Main> do return 0
Run Code Online (Sandbox Code Playgroud)

0

*Main> do (Just 0)
Run Code Online (Sandbox Code Playgroud)

只是0

*Main> do return (Just 0)
Run Code Online (Sandbox Code Playgroud)

只是0

*Main> do Nothing
Run Code Online (Sandbox Code Playgroud)

没有

*Main> do return Nothing
Run Code Online (Sandbox Code Playgroud)

没有

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

doReturn :: Monad m => a -> m a
doReturn x = do return x
Run Code Online (Sandbox Code Playgroud)

为什么会do x和do return x同样地进行评价,而当将他们不这样做?

我试图理解Monad,这已经足够的教程和讨论,但我无法弄清楚.

也就是说即使是后写

不要阅读monad教程.

所以,我觉得弄脏手可能会有所帮助.

我真的很感谢谁帮我离开这里(我的意思是do和return,不Monad,我知道这将需要一些天).

lef*_*out 19

do在一个单独的表达式上完成任何事情:它只是一个语法指示,表明你可以在这里使用动作排序(这需要一个monad),但如果你不这样做,那么它与在图层中包装一个表达式具有相同的效果多余的括号.

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

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
Run Code Online (Sandbox Code Playgroud)

现在问题是为什么return在这里没有做任何事情.嗯,实际上确实如此,你只是看不到它,因为GHCi隐藏了实现细节.GHCi有两种根本不同的交互式评估模式:

  1. IO动作执行,然后将结果print编辑.
  2. 其他所有内容都是print原样.

至关重要的是,IO在继续使用2之前,GHCi很难将所有内容都解释为一个动作.因此,如果你给它一个模糊的表达式return 0,它会注意到一个可能的实例化IO Integer.它立即默认为,执行这个副作用自由动作,因此你在结果中看到的只是0.这只会发生,IO但不适用于任何其他monad:

Prelude> return 0 :: IO Integer
0
Prelude> return 0 :: Maybe Integer
Just 0
Prelude> return 0 :: [] Integer
[0]
Run Code Online (Sandbox Code Playgroud)

GHCi恰好默认为IOmonad处于模糊状态时,但在Haskell中就不会发生这种情况.