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
(这是一个变相的列表理解)。
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
(这是一个变相的列表理解)。