假设我有一个T a b
类型,我想写一个实例声明,例如Functor
的实例声明范围超过a
且不是 b
。如果没有定义newtype
?
我读了What is the rule of the order of multiple type variables in haskell?,这让我相信这是不可能的,但这对我来说似乎是完全随意的。
我希望的是:
instance Functor (T * b)
答案 0 :(得分:5)
这不是任意的。这是Hindley-Milner类型推理如何与更高级的类型和curried类型构造函数应用一起工作的。类型变量的统一基于生成类型构造函数的概念。也就是说,如果(f a) ~ (g b)
,则f ~ g
和a ~ 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没有的几个实例。