You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何部分应用的类型构造器仅可在类型参数位置传入?

底层规则本质:固定Kind的内置类型构造器 和 支持多态Kind的类型变量 的推导逻辑差异

基础前提:Kind 规则

Haskell 中所有类型构造器都有对应的Kind,可以理解为「类型层面的类型」:

  • 可以直接用作值类型的构造器Kind为*,比如Int、Bool
  • 带参数的类型构造器的Kind对应类型函数的签名,比如接收1个类型参数的Maybe的Kind为* -> *,接收2个类型参数的Either的Kind为* -> * -> *

为什么bar会被拒绝

bar :: t [f a] -> f a b -- rejected
bar = undefined

[f a]是[] (f a)的语法糖,列表构造器[]是内置的固定Kind的类型,它的Kind是* -> *,只能接收Kind为*的类型作为参数。因此这里可以推导得到:f a的Kind必须是*,进一步可得f的Kind是* -> *。
但返回值里的f a b要求f接收2个类型参数,对应的Kind应该是* -> * -> *,两者推导出来的f的Kind完全冲突,因此编译器直接报错。


为什么foo可以被接受

foo :: t (f a) -> f a b -- accepted
foo = undefined

和固定Kind的[]不同,签名里的t、f都是未绑定具体实现的类型变量,编译器会自动推导它们的Kind来满足所有约束,不会有固定Kind的限制:

  1. 先看返回值f a b:f需要接收2个*类型的参数a、b,因此f的Kind推导为* -> * -> *,a、b的Kind都是*
  2. 再看参数里的f a:给Kind为* -> * -> *的f传入1个*类型的a,得到的f a的Kind是* -> *
  3. 最后看t:它接收f a作为参数,因此t的Kind自动推导为(* -> *) -> *,完全符合规则,没有任何冲突,所以签名可以通过检查。

内容的提问来源于stack exchange,提问作者user5536315

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 01:12:01