问题描述
我定义了一个自定义 GADT,其中类型构造函数对类型变量具有类型类约束,如下所示:
data MyGadt x where
Sample :: Show a => a -> MyGadt a
现在,如果我定义以下两个函数:
foo (Sample a) = show a
bar a = Sample a
GHC 为它们推断出让我有点恼火的类型。
foo :: MyGadt x -> [Char]
没有提及 Show
的 x
约束,而 bar :: Show a => a -> MyGadt a
确实要求明确提及约束。
我假设我不必提及约束,因为它是在 GADT 定义中声明的。
我能想到的唯一原因是 GADT 在函数中的位置。我对此不是很深入,但据我所知,MyGadt
在 foo
中处于积极位置,在 bar
中处于消极位置。
我什么时候必须明确提及类型类约束,GHC 什么时候根据 GADTs 类型构造函数的约束自己弄清楚?
解决方法
重点是使用 GADT,您希望约束出现在 bar
的签名中,而不是 foo
。如果您不想要那样,那么您可以使用普通的旧 newtype
代替:
newtype MyAdt = Sample a
foo :: Show a => MyAdt a -> String
foo (Sample a) = show a
bar :: a -> MyAdt a
bar = Sample
在既不 foo
也不 bar
中设置约束显然是行不通的,因为那样你就可以例如
showFunction :: (Integer -> Integer) -> String
showFunction = foo . bar