奇怪的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 ...
不清楚是评估e1
, e2
还是两者。
目前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?