Haskell 类型推断与 GADT 和类型变量上的类型类约束

问题描述

我定义了一个自定义 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] 没有提及 Showx 约束,而 bar :: Show a => a -> MyGadt a 确实要求明确提及约束。

我假设我不必提及约束,因为它是在 GADT 定义中声明的。 我能想到的唯一原因是 GADT 在函数中的位置。我对此不是很深入,但据我所知,MyGadtfoo 中处于积极位置,在 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