奇怪的ghc错误信息,“我的大脑爆炸了”?

当我尝试使用proc语法(使用Netwire和Vinyl)对GADT进行模式匹配时:

sceneRoot = proc inputs -> do
            let (Identity camera :& Identity children) = inputs 
            returnA -< (<*>) (map (rGet draw) children) . pure

我得到(很奇怪)编译器错误,从ghc-7.6.3

  My brain just exploded
    I can't handle pattern bindings for existential or GADT data constructors.
    Instead, use a case-expression, or do-notation, to unpack the constructor.
    In the pattern: Identity cam :& Identity childs

当我将模式放入proc (...)模式时,我得到一个类似的错误。 为什么是这样? 它不健全,还是只是未实现?


考虑GADT

data S a where
  S :: Show a => S a

并执行代码

foo :: S a -> a -> String
foo s x = case s of
            S -> show x

在基于字典的Haskell实现中,人们会期望值s携带类字典,并且该case从所述字典中提取show函数,以便可以执行show x

如果我们执行

foo undefined (x::Int -> 4::Int)

我们得到一个例外。 在操作上,这是预料之中的,因为我们无法访问字典。 更一般地case (undefined :: T) of K -> ...是怎么回事,因为它迫使的评价产生错误undefined (前提是T不是newtype )。

现在考虑代码(让我们假装编译)

bar :: S a -> a -> String
bar s x = let S = s in show x

和执行

bar undefined (x::Int -> 4::Int)

这应该怎么做? 有人可能会争辩说,它应该产生与foo相同的异常。 如果是这样的话,参考透明度就意味着这一点

let S = undefined :: S (Int->Int) in show (x::Int -> 4::Int)

同样的例外情况也会失败。 这意味着let正在评估undefined表达式,与例如非常不同

let [] = undefined :: [Int] in 5

评估为5

实际上, let中的模式是懒惰的:他们不强制对表达式进行评估,这与case不同。 这就是为什么例如

let (x,y) = undefined :: (Int,Char) in 5

成功评估为5

有人可能想使let S = e in e'评估e如果show需要在e' ,但感觉相当怪异。 而且,当评价let S = e1 ; S = e2 in show ... let S = e1 ; S = e2 in show ...不清楚是评估e1e2还是两者。

目前GHC选择禁止所有这些情况都有一条简单规则:消除GADT时不会出现懒惰模式。

链接地址: http://www.djcxy.com/p/43073.html

上一篇: Odd ghc error message, "My brain just exploded"?

下一篇: Which GHC type system extensions should I try to learn first?