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

时间:2014-05-08 02:10:59

标签: haskell gadt arrows

当我尝试使用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 (...)模式中时,我收到类似的错误。为什么是这样?它不健全,还是只是未实现?

1 个答案:

答案 0 :(得分:10)

考虑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函数,以便{ {1}}可以执行。

如果我们执行

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中的模式是 lazy :与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 ...e1还是两者。

目前GHC选择用一个简单的规则禁止所有这些案例:消除GADT时没有懒惰模式。