实例声明中的类型变量的顺序

时间:2017-05-23 12:27:52

标签: haskell

假设我有一个T a b类型,我想写一个实例声明,例如Functor的实例声明范围超过a不是 b。如果没有定义newtype

,这是否可行

我读了What is the rule of the order of multiple type variables in haskell?,这让我相信这是不可能的,但这对我来说似乎是完全随意的。

我希望的是:

instance Functor (T * b)

1 个答案:

答案 0 :(得分:5)

这不是任意的。这是Hindley-Milner类型推理如何与更高级的类型和curried类型构造函数应用一起工作的。类型变量的统一基于生成类型构造函数的概念。也就是说,如果(f a) ~ (g b),则f ~ ga ~ b,其中~类型相等。

我们将其应用于统一(fmap f someT)这样的表达式,用于someT :: T a b。我将首先提供除someT新鲜类型变量以外的所有内容,以统一的方式工作。

someT :: T a b
fmap :: (c -> d) -> f c -> f d
f :: e

由于fmap被提供f作为第一个参数,我们统一(c -> d) ~ e。所以..

fmap f :: f c -> f d
someT :: T a b

这就是生成性的来源。从这里开始,我们看到(f c) ~ (T a b)。为清楚起见,我添加一些额外的括号:(f c) ~ ((T a) b)。这就是类型构造函数在Haskell中的工作方式 - 它们与术语级函数相同。通过生成,f ~ (T a)c ~ b

然后从那起:

fmap f someT :: T a d

因此,Functor实例必须仅对T类型的第二个类型参数起作用,这一定是正确的。

当然这一切都可以追溯到类型推断算法。你可以放弃Hindley-Milner或curried类型的构造函数来使事情有所不同。但结果与Haskell的结果大不相同,只是允许Haskell没有的几个实例。