GHCI monadic绑定严格吗?

时间:2018-01-26 01:31:35

标签: haskell ghci

GHC手册说明了GHCI中的一元结合:

  

两种类型的绑定之间的另一个重要区别是   monadic bind(p < - e)是严格的(它评估e),而与   let form,表达式不会立即评估:

(来自here

但我可以在GHCI中这样做:

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

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

3 个答案:

答案 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

(这是伪装的清单理解)。