你可以在网上找到以下资料:

Higher kinded type == type constructor? class AClass[T]{...} // For example, class List[T] Some say this is a higher kinded type, because it abstracts over types which would be compliant with the definition. Higher kinded types are types which take other types and construct a new type These though are also known as type constructor. (For example, in Programming in Scala). Higher kinded type == type constructor which takes type constructor as a type parameter? In the paper Generics of a Higher Kind, you can read ... types that abstract over types that abstract over types ('higher-kinded types') ..." which suggests that class XClass[M[T]]{...} // or trait YTrait[N[_]]{...} // e.g. trait Functor[F[_]] is a higher kinded type.

因此,考虑到这一点,很难区分类型构造函数,高级类型类型和将类型构造函数作为类型参数的类型构造函数,因此出现了上面的问题。


当前回答

让我通过消除歧义来弥补开始时的一些困惑。我喜欢用价值层面的类比来解释这一点,因为人们往往更熟悉它。

类型构造函数是一种类型,可以应用于类型参数以“构造”类型。 值构造函数是一个可以应用于值参数以“构造”值的值。

值构造函数通常称为“函数”或“方法”。这些“构造函数”也被认为是“多态的”(因为它们可以用来构造不同“形状”的“东西”),或者是“抽象的”(因为它们抽象了不同多态实例化之间的变化)。

在抽象/多态性上下文中,一阶指的是抽象的“单次使用”:对一个类型进行一次抽象,但该类型本身不能对任何东西进行抽象。Java 5泛型是一阶的。

上述抽象特征的一阶解释是:

类型构造函数是一种可以应用于适当类型参数以“构造”适当类型的类型。 值构造函数是一个值,您可以将其应用到适当的值参数以“构造”适当的值。

为了强调没有涉及抽象(我猜你可以称之为“零阶”,但我在任何地方都没有见过这种用法),例如值1或类型String,我们通常说某个值或类型是“适当的”值或类型。

适当的值是“立即可用”的,因为它不等待参数(它不抽象参数)。可以把它们看作是可以轻松打印/检查的值(序列化函数是欺骗!)

正确的类型是对值(包括值构造函数)进行分类的类型,类型构造函数不对任何值进行分类(它们首先需要应用于正确的类型参数以产生正确的类型)。要实例化一个类型,它必须是一个合适的类型(但还不够)。(它可能是一个抽象类,也可能是一个您无法访问的类。)

“高阶”只是一个通用术语,意思是重复使用多态性/抽象。对于多态类型和值也是如此。具体地说,高阶抽象是对某物的抽象,再对某物的抽象。对于类型,术语“高类”是更一般的“高阶”的特殊用途版本。

因此,我们的描述的高阶版本变成:

类型构造函数是一种可以应用于类型参数(适当类型或类型构造函数)以“构造”适当类型(构造函数)的类型。 值构造函数是一个可以应用于值参数(正确值或值构造函数)以“构造”正确值(构造函数)的值。

因此,“高阶”仅仅意味着当您说“对X进行抽象”时,您是认真的!被抽象的X并没有失去它自己的“抽象权利”:它可以抽象它想要的一切。(顺便说一下,我在这里使用动词“抽象”的意思是:省略一些对值或类型的定义不重要的东西,这样它就可以由抽象的用户作为参数来改变/提供。)

以下是一些恰当、一阶和高阶值和类型的例子(灵感来自Lutz通过电子邮件提出的问题):

                   proper    first-order           higher-order

values             10        (x: Int) => x         (f: (Int => Int)) => f(10)
types (classes)    String    List                  Functor
types              String    ({type λ[x] = x})#λ   ({type λ[F[x]] = F[String]})#λ

其中所使用的类定义为:

class String
class List[T]
class Functor[F[_]]

为了避免通过定义类来避免间接,你需要以某种方式表达匿名类型函数,这在Scala中是无法直接表达的,但你可以使用结构类型,没有太多的语法开销(#λ style是由于https://stackoverflow.com/users/160378/retronym afaik):

在某个假设的支持匿名类型函数的Scala未来版本中,您可以将示例中的最后一行缩短为:

types (informally) String    [x] => x              [F[x]] => F[String]) // I repeat, this is not valid Scala, and might never be

(就我个人而言,我后悔曾经谈论过“高级类型”,毕竟他们只是类型!当你绝对需要消除歧义时,我建议说“类型构造函数形参”,“类型构造函数成员”,或“类型构造函数别名”,以强调你谈论的不仅仅是正确的类型。)

ps:更复杂的是,“多态”在另一种方式上是模棱两可的,因为一个多态类型有时意味着一个普遍量化的类型,例如Forall T, T => T,这是一个适当的类型,因为它对多态值进行了分类(在Scala中,这个值可以写成结构类型{def apply[T](x: T): T = x})

其他回答

Scala REPL提供:kind命令

scala> :help kind

:kind [-v] <type>
Displays the kind of a given type.

例如,

scala> trait Foo[A]
trait Foo

scala> trait Bar[F[_]]
trait Bar

scala> :kind -v Foo
Foo's kind is F[A]
* -> *
This is a type constructor: a 1st-order-kinded type.

scala> :kind -v Foo[Int]
Foo[Int]'s kind is A
*
This is a proper type.

scala> :kind -v Bar
Bar's kind is X[F[A]]
(* -> *) -> *
This is a type constructor that takes type constructor(s): a higher-kinded type.

scala> :kind -v Bar[Foo]
Bar[Foo]'s kind is A
*
This is a proper type.

help提供了清晰的定义,所以我认为有必要将其完整地发布在这里(Scala 2.13.2)

scala> :help kind

:kind [-v] <type>
Displays the kind of a given type.

    -v      Displays verbose info.

"Kind" is a word used to classify types and type constructors
according to their level of abstractness.

Concrete, fully specified types such as `Int` and `Option[Int]`
are called "proper types" and denoted as `A` using Scala
notation, or with the `*` symbol.

    scala> :kind Option[Int]
    Option[Int]'s kind is A

In the above, `Option` is an example of a first-order type
constructor, which is denoted as `F[A]` using Scala notation, or
* -> * using the star notation. `:kind` also includes variance
information in its output, so if we ask for the kind of `Option`,
we actually see `F[+A]`:

    scala> :k -v Option
    Option's kind is F[+A]
    * -(+)-> *
    This is a type constructor: a 1st-order-kinded type.

When you have more complicated types, `:kind` can be used to find
out what you need to pass in.

    scala> trait ~>[-F1[_], +F2[_]] {}
    scala> :kind ~>
    ~>'s kind is X[-F1[A1],+F2[A2]]

This shows that `~>` accepts something of `F[A]` kind, such as
`List` or `Vector`. It's an example of a type constructor that
abstracts over type constructors, also known as a higher-order
type constructor or a higher-kinded type.

(这个答案试图用一些图形和历史信息来装饰阿德里安·摩尔的答案。)

高级类型从2.5开始就是Scala的一部分。

Before that Scala, as Java till now, did not allow to use type constructor ("generics" in Java) to be used as type parameter to a type constructor. e.g. trait Monad [M[_]] was not possible. In Scala 2.5 the type system had been extended by the ability to classify types on a higher level (known as type constructor polymorphism). These classifications are known as kinds. (Picture derived from Generics of a Higher Kind) The consequence is, that type constructor (e.g. List) could be used just as other types in type parameter position of type constructors and so they became first class types since Scala 2.5. (Similar to functions which are first class values in Scala). In the context of a type system supporting higher kinds, we can distinguish proper types, types like Int or List[Int] from first-order types like List and types of a higher kind like Functor or Monad (types which abstract over types which abstract over types). The type system of Java on the other side does not support kinds and therefore has no types of a "higher kind". So this has to be seen against the background of the supporting type system. In the case of Scala you often see examples of a type constructor like trait Iterable[A, Container[_]] with the headline "Higher kinded types", e.g. in Scala for generic programmers, section 4.3 This is sometimes missleading, because many refer to Container as higher kinded type and not Iterable, but what is more precise is, the use of Container as type constructor parameter of a higher kinded (higher-order) type here Iterable.

让我通过消除歧义来弥补开始时的一些困惑。我喜欢用价值层面的类比来解释这一点,因为人们往往更熟悉它。

类型构造函数是一种类型,可以应用于类型参数以“构造”类型。 值构造函数是一个可以应用于值参数以“构造”值的值。

值构造函数通常称为“函数”或“方法”。这些“构造函数”也被认为是“多态的”(因为它们可以用来构造不同“形状”的“东西”),或者是“抽象的”(因为它们抽象了不同多态实例化之间的变化)。

在抽象/多态性上下文中,一阶指的是抽象的“单次使用”:对一个类型进行一次抽象,但该类型本身不能对任何东西进行抽象。Java 5泛型是一阶的。

上述抽象特征的一阶解释是:

类型构造函数是一种可以应用于适当类型参数以“构造”适当类型的类型。 值构造函数是一个值,您可以将其应用到适当的值参数以“构造”适当的值。

为了强调没有涉及抽象(我猜你可以称之为“零阶”,但我在任何地方都没有见过这种用法),例如值1或类型String,我们通常说某个值或类型是“适当的”值或类型。

适当的值是“立即可用”的,因为它不等待参数(它不抽象参数)。可以把它们看作是可以轻松打印/检查的值(序列化函数是欺骗!)

正确的类型是对值(包括值构造函数)进行分类的类型,类型构造函数不对任何值进行分类(它们首先需要应用于正确的类型参数以产生正确的类型)。要实例化一个类型,它必须是一个合适的类型(但还不够)。(它可能是一个抽象类,也可能是一个您无法访问的类。)

“高阶”只是一个通用术语,意思是重复使用多态性/抽象。对于多态类型和值也是如此。具体地说,高阶抽象是对某物的抽象,再对某物的抽象。对于类型,术语“高类”是更一般的“高阶”的特殊用途版本。

因此,我们的描述的高阶版本变成:

类型构造函数是一种可以应用于类型参数(适当类型或类型构造函数)以“构造”适当类型(构造函数)的类型。 值构造函数是一个可以应用于值参数(正确值或值构造函数)以“构造”正确值(构造函数)的值。

因此,“高阶”仅仅意味着当您说“对X进行抽象”时,您是认真的!被抽象的X并没有失去它自己的“抽象权利”:它可以抽象它想要的一切。(顺便说一下,我在这里使用动词“抽象”的意思是:省略一些对值或类型的定义不重要的东西,这样它就可以由抽象的用户作为参数来改变/提供。)

以下是一些恰当、一阶和高阶值和类型的例子(灵感来自Lutz通过电子邮件提出的问题):

                   proper    first-order           higher-order

values             10        (x: Int) => x         (f: (Int => Int)) => f(10)
types (classes)    String    List                  Functor
types              String    ({type λ[x] = x})#λ   ({type λ[F[x]] = F[String]})#λ

其中所使用的类定义为:

class String
class List[T]
class Functor[F[_]]

为了避免通过定义类来避免间接,你需要以某种方式表达匿名类型函数,这在Scala中是无法直接表达的,但你可以使用结构类型,没有太多的语法开销(#λ style是由于https://stackoverflow.com/users/160378/retronym afaik):

在某个假设的支持匿名类型函数的Scala未来版本中,您可以将示例中的最后一行缩短为:

types (informally) String    [x] => x              [F[x]] => F[String]) // I repeat, this is not valid Scala, and might never be

(就我个人而言,我后悔曾经谈论过“高级类型”,毕竟他们只是类型!当你绝对需要消除歧义时,我建议说“类型构造函数形参”,“类型构造函数成员”,或“类型构造函数别名”,以强调你谈论的不仅仅是正确的类型。)

ps:更复杂的是,“多态”在另一种方式上是模棱两可的,因为一个多态类型有时意味着一个普遍量化的类型,例如Forall T, T => T,这是一个适当的类型,因为它对多态值进行了分类(在Scala中,这个值可以写成结构类型{def apply[T](x: T): T = x})

像Int和Char这样的普通类型,其实例是值,是*。像Maybe这样的一元类型构造函数是* -> *;像Either这样的二进制类型构造函数有(curried) kind * -> * -> *,等等。可以将Maybe和Either这样的类型视为类型级函数:它们接受一个或多个类型,并返回一个类型。

如果一个函数的阶数大于1,那么它就是高阶函数,这里的阶数(非正式地)是函数箭头左边的嵌套深度:

(0: 1:: Int Order 1: chr:: Int -> Char 订单2:修复::(- >)- >,地图::(a - > b) - > [a] - > [b] 阶3:(A -> B) -> C) -> D 阶4:(((A -> B) -> C) -> D) -> E

所以,长话短说,高级类型只是一个类型级的高阶函数,它抽象了类型构造函数:

顺序0:Int:: * 顺序1:可能是::* -> * Order 2: Functor::(* -> *) -> Constraint-higher-kinded:将一元类型构造函数转换为类型类约束

我会说:高级类型抽象于类型构造函数之上。例如,考虑

trait Functor [F[_]] {
   def map[A,B] (fn: A=>B)(fa: F[A]): F[B]
}

这里Functor是一个“高级类类型”(在“高级类泛型”论文中使用)。它不是像List那样的具体(“一阶”)类型构造函数(仅对正确类型进行抽象)。它抽象了所有一元(“一阶”)类型构造函数(用F[_]表示)。

或者换句话说:在Java中,我们有明确的类型构造函数(例如List<T>),但我们没有“高级类型类型”,因为我们不能对它们进行抽象(例如,我们不能编写上面定义的Functor接口——至少不能直接编写)。

术语“高阶(类型构造函数)多态性”用于描述支持“高级类型”的系统。