我试图绕过GADT,我怀疑一些魔法正在发生,我不明白。
请考虑以下事项:
class C t
data T a where
T :: (C a) => { getT :: a } -> T a
f :: C a => a -> ()
f = undefined
class D t where
g :: t a -> ()
instance D T where
g (T x) = f x
这一切都很好并且编译成功。
现在考虑对T:
稍微不同的实例定义instance D T where
g x = f (getT x)
这看起来与上面完全相同,但是存在编译错误。这里发生了什么?数据类型T
没有存在变量,它只有一个简单的约束,它只是构造函数,但它就是它。
答案 0 :(得分:7)
这里发生的是模式匹配
g (T x) = f x
告诉typechecker您已经满足约束C a
,因此您可以使用f
。如果没有模式匹配,则永远不会引入C a
,因此无法满足约束条件。
它的作用使得值T something :: T a
还包含C a
的字典,并在T
上进行模式匹配时可用。但是,使用getT
并不能让您找到C a
的字典(正如您从getT :: T a -> a
的类型中看到的那样)。
对于后人,错误是
• No instance for (C a) arising from a use of ‘f’
Possible fix:
add (C a) to the context of
the type signature for:
g :: T a -> ()
• In the expression: f (getT x)
In an equation for ‘g’: g x = f (getT x)
In the instance declaration for ‘D T’