GHCI monadic bind 严格吗?

Is GHCI monadic bind strict?

GHC 手册对 GHCI 中的单子绑定进行了说明:

Another important difference between the two types of binding is that the monadic bind (p <- e) is strict (it evaluates e), whereas with the let form, the expression isn’t evaluated immediately:

(来自 here

但我可以在 GHCI 中这样做:

λ: x <- return $ error ":("
λ: :sprint x
x = _

这似乎表明monadic绑定并不严格。我错过了什么?

在Haskell中,我们将的评估与计算的执行分开。 return (error "") 是成功返回未定义值的计算,绑定时不计算该值。 error "" :: IO a 是未定义的计算,会立即失败。

请记住,严格的函数意味着 f ⊥ = ⊥。考虑:

ghci> x <- return undefined
-- no error

这意味着 return undefined >>= \x -> ... 不是 ⊥,但这并没有真正说明 >>= 的严格性,因为 return。然而,这:

ghci> y <- undefined
*** Exception: Prelude.undefined

是手册中提到的情况,它表明左参数中的绑定是严格的,因为undefined >>= (\y -> ...)是⊥。最后,

ghci> :set -XBangPatterns
ghci> !z <- return undefined
*** Exception: Prelude.undefined

这一行显示了如果我们给它一个严格的函数作为参数会发生什么,所以我们知道 return undefined >>= f 是 ⊥ 如果 f 是严格的 .这实际上遵循单子法则return x >>= f = f x,所以return ⊥ >>= f = f ⊥ = ⊥

我相信这是在谈论绑定,即模式匹配过程。

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

(这是一个变相的列表理解)。