一些术语:
- 正确的类型(例如 Int)
- 一阶类型(例如 List[_]);我们也可以说一阶类型
- 更高种类的类型(例如 Monad[M[_])
当你说
trait Monoid[A] {
def op(a1: A, a2: A): A
def zero: A
}
val listMonoid = new Monoid[List[Int]] {
def op(l: List[Int], l2: List[Int]) = List(1,2)
def zero = List(1,2)
}
你正在参数化Monoid
具有某种类型 A 的特征,它可以(如您所注意到的)是一个简单类型,也称为正确类型(例如Int
)或参数化类型(例如List[Int]
, 甚至List[Set[Map[Int, Int]]
)。这使得Monoid
一阶类型。我们也可以说它是一个一元类型构造函数 - 它需要一种类型来生成最终类型。
与 Monoid 不同,一些抽象(例如 Monad)需要由类型构造函数参数化。 Int 不再起作用了。它需要是“某种可以产生另一种类型的类型”。由类型构造函数参数化的抽象(即由“一阶类型”参数化)是高等类型。这是一个例子:
trait Monad[M[_]] {
def op[A, B](m: M[A], f: A => M[B]): M[B]
def zero[A](a: A): M[A]
}
object ListMonad extends Monad[List] {
def op[A, B](m: List[A], f: A => List[B]) = m.flatMap(f)
def zero[A](a: A) = List[A](a)
}
val listMonad = ListMonad.zero(42)
val result = ListMonad.op(listMonad, (i: Int) => List(i - 1, i, i + 1))
// result = List(41, 42, 43)
So Monad
参数化为一阶类型(一元类型构造函数),这使得Monad
本身就是一个高等类型.
注意如何Monad
并不真正关心类级别上的“内部类型”本身,因为它将由方法定义op
and zero
。你也可以说trait Monad[M[A]]
并在类的定义点“修复”类型 AListMonad
(例如将其修复为 Int),但随后你就会失去灵活性(你的ListMonad
然后将只能构造和 flatMapList[Int]
你需要一个不同的课程,比如说,List[String]
).
这与 Monoid 不同,Monoid 不是更高级的类型;它不需要类型构造函数来生成类型。如果它需要它,那么你永远不会拥有,比如说,Monoid[Int]
,因为 Int 不是类型构造函数。
另请注意我是如何说 Monad 需要一个unary类型构造函数,这意味着它只需要一种类型(不像 Map 需要两种类型)。类型构造函数通常用星号和箭头表示:
- 一元一阶类型构造函数是
* -> *
(它采用单一类型并生成最终类型,例如 Set)
- 二进制一阶类型构造函数是
* -> * -> *
(二进制类型构造函数,采用两种类型来生成最终类型,例如 Map)
- 一元高级类型是
(* -> *) -> *
(采用单个一元类型构造函数来生成最终类型,例如 Monad)
etc.
因此,一阶类型采用简单/具体/适当的类型并生成最终类型,而高级类型则高一级;它需要一阶类型来生成最终类型。
EDIT:
在“编辑”部分回答您的问题:好的,我想我知道什么让您感到困惑。listMonoid
不是一种类型,因此它不可能是更高级的类型。这是一种方法。Monad[List[Int]]
是完全解析的类型。Monad[F[A]]
也得到彻底解决。然而,Monad
本身是一个高阶类型。
让我将其与函数进行类比。如果你有一个函数foo(x: Int)
,然后函数调用如foo(42)
or foo(someIntegerValue)
产生具体的价值。这些类似于Monad[List[Int]]
and Monad[F[A]]
。然而,foo
本身就是一个函数,就像Monad
本身是一个类型构造函数。
If foo
采用一个简单值(不是函数),它是一阶函数;如果它接受或返回一个函数,那么它是一个高阶函数。与类型构造函数相同。如果它采用简单类型,则它是一阶类型构造函数。例子:List
。如果它采用另一个类型构造函数,则它是高阶类型构造函数(也称为高种类类型)。例子:Monad
.
不要将解析类型与类型构造函数混合。思考功能是否有意义foo
是否是高阶的;这取决于它的参数和返回类型。但思考是否foo(42)
是否是高阶的;这不是一个函数,而是一个函数应用,从而产生值。Monad[List[Int]]
不是类型构造函数,而是类型构造函数的应用List
到类型构造函数Monad
(这是高阶的)。相似地,Monoid[List[Int]]
不是类型构造函数,而是类型的应用List[Int]
到类型构造函数Monoid
(这是一阶)。类型构造函数更高阶的称为 HKT。谈论 HKT 并指向具体的解析类型(由于应用某种类型构造函数而创建)是没有意义的。