这可能是一个愚蠢的问题,但我无法弄清楚以下行为的基本规则:
foo :: t (f a) -> f a b -- accepted
foo = undefined
bar :: t [f a] -> f a b -- rejected
bar = undefined
f
应用到a
和a b
分别bar
导致类错误并因此被拒绝是完全有道理的。但为什么会被foo
接受?
这可能是一个愚蠢的问题,但我无法弄清楚以下行为的基本规则:
foo :: t (f a) -> f a b -- accepted
foo = undefined
bar :: t [f a] -> f a b -- rejected
bar = undefined
f
应用到a
和a b
分别bar
导致类错误并因此被拒绝是完全有道理的。但为什么会被foo
接受?
是那种f
。
由于返回类型f a b
- 即f
应用于两个参数, - 这意味着f :: Type -> Type -> Type
.
但是 thenf a
被用作列表元素[f a]
- 并且列表元素必须是Type
,这意味着f a :: Type
,这意味着f :: Type -> Type
。
不匹配。
foo
之所以有效,是因为可以部分应用类型。也就是说,如果f :: Type -> Type -> Type
,那么f a :: Type -> Type
。然后, typet
允许有一个参数 kind Type -> Type
,所以一切都匹配。
重申上述内容:
foo
有效,因为 typet
可能有一个参数 kind Type -> Type
。bar
不起作用,因为 type []
(aka "list") 必须有一个参数 kind Type
。