[do x] 和 [do return x] 什么时候评估不同?
When do [do x] and [do return x] evaluate differently?
*Main> do 0
0
*Main> do return 0
0
*Main> do (Just 0)
Just 0
*Main> do return (Just 0)
Just 0
*Main> do Nothing
Nothing
*Main> do return Nothing
Nothing
bareDo :: a -> a
bareDo x = do x
doReturn :: Monad m => a -> m a
doReturn x = do return x
为什么 do x
和 do return x
评估相同,什么时候不评估?
我正在努力理解 Monad
,教程已经够多了,discussion 但我还是搞不懂。
那甚至是post写作
Don't read the monad tutorials.
所以,我想亲自动手可能会有所帮助。
非常感谢帮助我离开这里的人(我指的是 do
和 return
,而不是 Monad
。我知道这需要几天时间)。
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
现在的问题是 为什么 return
在这里没有完成任何事情。好吧,实际上它确实如此,只是您看不到它,因为 GHCi 隐藏了实现细节。 GHCi 有两种根本不同的交互式评估模式:
IO
操作 执行 ,然后 print
编辑。
- 其他所有内容
print
按原样编辑。
至关重要的是,GHCi 在继续 2 之前相当努力地将所有内容解释为 IO
操作。因此,如果您给它一个模棱两可的表达式,例如 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]
当 monad 不明确时,GHCi 恰好默认为 IO
,但在 Haskell 中不会发生这种情况。
好的答案:从不,因为 return :: Monad m => a -> m a
拿了一个物体并将其放入盒子中。
正确但不可用的答案:当 x 是给定 monad 的 return
的定点时。
*Main> do 0
0
*Main> do return 0
0
*Main> do (Just 0)
Just 0
*Main> do return (Just 0)
Just 0
*Main> do Nothing
Nothing
*Main> do return Nothing
Nothing
bareDo :: a -> a
bareDo x = do x
doReturn :: Monad m => a -> m a
doReturn x = do return x
为什么 do x
和 do return x
评估相同,什么时候不评估?
我正在努力理解 Monad
,教程已经够多了,discussion 但我还是搞不懂。
那甚至是post写作
Don't read the monad tutorials.
所以,我想亲自动手可能会有所帮助。
非常感谢帮助我离开这里的人(我指的是 do
和 return
,而不是 Monad
。我知道这需要几天时间)。
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
现在的问题是 为什么 return
在这里没有完成任何事情。好吧,实际上它确实如此,只是您看不到它,因为 GHCi 隐藏了实现细节。 GHCi 有两种根本不同的交互式评估模式:
IO
操作 执行 ,然后print
编辑。- 其他所有内容
print
按原样编辑。
至关重要的是,GHCi 在继续 2 之前相当努力地将所有内容解释为 IO
操作。因此,如果您给它一个模棱两可的表达式,例如 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]
当 monad 不明确时,GHCi 恰好默认为 IO
,但在 Haskell 中不会发生这种情况。
好的答案:从不,因为 return :: Monad m => a -> m a
拿了一个物体并将其放入盒子中。
正确但不可用的答案:当 x 是给定 monad 的 return
的定点时。