解构GADT:我在哪里失去了背景?

时间:2013-09-05 16:42:00

标签: haskell gadt

我有这种类型和这些功能:

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

1 个答案:

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