我有这种类型和这些功能:
data Tag a where
Tag :: (Show a, Eq a, Ord a, Storable a, Binary a) => a -> BL.ByteString -> Tag a
getVal :: Tag a -> a
getVal (Tag v _) = v
isBigger :: Tag a -> Tag a -> Bool
a `isBigger` b = (getVal a) > (getVal b)
代码没有进行类型检查:
No instance for (Ord a)
arising from a use of `>'
In the expression: (getVal a) > (getVal b)
In an equation for `isBigger':
a isBigger b = (getVal a) > (getVal b)
但我不明白为什么不。 Tag a
具有上下文(Show a, Eq a, Ord a, Storable a, Binary a)
,getVa
l应该保留此上下文。我做错了,还是这是GADTs扩展的限制?
这有效:
isBigger :: Tag a -> Tag a -> Bool
(Tag a _) `isBigger` (Tag b _) = a > b
编辑:我将示例更改为最小示例
编辑:好的,为什么不这个 typecheck?
isBigger :: Tag a -> Tag a -> Bool
isBigger ta tb =
let (Tag a _) = ta
(Tag b _) = tb
in
a > b
答案 0 :(得分:6)
getVal
的类型签名不正确,您需要类型
getVal (Storable a, Ord a, ...) => Tag a -> a
getVal (Tag v _) = v
这不是推断的原因是因为你可以做像
这样的事情 doh :: Tag a
doh = undefined
现在a
对它没有任何限制。我们可以做类似
getVal (doh :: Tag (IO Int)) == getVal (doh :: Tag (IO Int))
如果getVal
有这些限制。
Tag
的唯一非底部实例对它们有类型类约束,但这对于类型检查器是不够的,因为它与底部不一致。
回答新问题
解构这样的类型时
foo tag = let (Tag a _) = tag
(Tag b _) = tag
in a > b
GHC没有正确地统一它们。我怀疑这是因为在达到模式匹配时,类型检查器已经确定了a
的类型,但是如果达到顶级匹配,它将正确统一。
foo (Tag a _) (Tag b _) = a > b