GHC手册说明了GHCI中的一元结合:
两种类型的绑定之间的另一个重要区别是 monadic bind(p < - e)是严格的(它评估e),而与 let form,表达式不会立即评估:
(来自here)
但我可以在GHCI中这样做:
λ: x <- return $ error ":("
λ: :sprint x
x = _
这似乎表明monadic绑定并不严格。我错过了什么?
答案 0 :(得分:9)
请记住,严格的函数意味着f ⊥ = ⊥
。考虑:
ghci> x <- return undefined
-- no error
这意味着return undefined >>= \x -> ...
不是⊥,但由于>>=
,这并没有真正说明return
的严格性。但是,这个:
ghci> y <- undefined
*** Exception: Prelude.undefined
是手册所指的情况,并且它在左参数中显示bind是严格的,因为undefined >>= (\y -> ...)
是⊥。最后,
ghci> :set -XBangPatterns
ghci> !z <- return undefined
*** Exception: Prelude.undefined
这一行显示了如果我们给它一个严格的函数作为参数会发生什么,所以我们知道如果return undefined >>= f
是严格的,f
是⊥。这实际上遵循monad法return x >>= f = f x
,所以return ⊥ >>= f = f ⊥ = ⊥
答案 1 :(得分:7)
在Haskell中,我们将值的评估与计算的执行分开。 return (error "")
是一个成功返回未定义值的计算,绑定时不会计算该值。 error "" :: IO a
是未定义的计算,会立即失败。
答案 2 :(得分:4)
我相信这是关于绑定,即模式匹配过程。
let p = e in e'
相当于
case e of ~p -> e'
其中模式p
已更改为延迟绑定~p
。从本质上讲,let
会在模式前添加隐式~
。
例如,
let [x] = [] in "hello"
评估为"hello"
,没有运行时错误。
以do
表示法,绑定
do p <- e ; e'
转换为类似
的东西e >>= (\w -> case w of
p -> e'
_ -> fail "some message")
其中w
是一个新变量。请注意,p
在此处未获得~
,否则它将始终匹配,并且_ -> fail ...
案例无法访问。
这需要写例如。
filterRight :: [Either a b] -> [a]
filterRight xs = do
Right x <- xs
return x
(这是伪装的清单理解)。