您可以在网上找到以下内容:
高级类型 == 类型构造函数? class AClass[T]{...} // 例如,class List[T] 有人说这是一个更高种类的类型,因为它抽象了符合定义的类型。更高种类的类型是采用其他类型并构造新类型的类型。尽管也称为类型构造函数。 (例如,在 Scala 编程中)。更高种类的类型 == 类型构造函数,它将类型构造函数作为类型参数?在论文 Generics of a Higher Kind 中,您可以阅读 ... 抽象类型之上的类型('higher-kinded types')......" 这表明 class XClass[M[T]]{.. .} // 或者 trait YTrait[N[_]]{...} // 例如 trait Functor[F[_]] 是一个更高种类的类型。
所以考虑到这一点,很难区分类型构造函数、更高种类的类型和以类型构造函数作为类型参数的类型构造函数,因此上面的问题。
让我通过一些消歧来弥补开始的一些混乱。我喜欢用价值水平的类比来解释这一点,因为人们往往更熟悉它。
类型构造函数是一种类型,您可以将其应用于类型参数以“构造”类型。值构造函数是可以应用于值参数以“构造”值的值。
值构造函数通常称为“函数”或“方法”。这些“构造函数”也被称为“多态”(因为它们可用于构造不同“形状”的“东西”)或“抽象”(因为它们抽象了不同多态实例之间的变化)。
在抽象/多态的上下文中,一阶是指抽象的“一次性使用”:您对一个类型进行一次抽象,但该类型本身不能对任何东西进行抽象。 Java 5 泛型是一阶的。
上述抽象特征的一阶解释是:
类型构造函数是一种类型,您可以将其应用于正确的类型参数以“构造”正确的类型。值构造函数是一个值,您可以将其应用于正确的值参数以“构造”正确的值。
为了强调不涉及抽象(我想你可以称之为“零阶”,但我没有看到它在任何地方使用过),例如值 1
或类型 String
,我们通常说某事是“正确的”值或类型。
一个正确的值是“立即可用的”,因为它不等待参数(它不抽象它们)。将它们视为您可以轻松打印/检查的值(序列化函数是作弊!)。
正确的类型是对值进行分类的类型(包括值构造函数),类型构造函数不会对任何值进行分类(它们首先需要应用于正确的类型参数以产生正确的类型)。要实例化一个类型,有必要(但不充分)它是一个正确的类型。 (它可能是一个抽象类,或者您无权访问的类。)
“高阶”只是一个通用术语,表示重复使用多态性/抽象。对于多态类型和值来说,这意味着同样的事情。具体来说,高阶抽象抽象了一些抽象的东西。对于类型,术语“higher-kinded”是更一般的“higher-order”的特殊用途版本。
因此,我们表征的高阶版本变为:
类型构造函数是一种可以应用于类型参数(正确类型或类型构造函数)以“构造”正确类型(构造函数)的类型。值构造函数是可以应用于值参数(正确值或值构造函数)以“构造”正确值(构造函数)的值。
因此,“高阶”仅仅意味着当你说“对 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 中无法直接表达,但您可以使用结构类型而不会产生太多语法开销(#λ
样式是由于 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 中,这个value 可以写成结构类型 {def apply[T](x: T): T = x}
)
(这个答案试图通过一些图形和历史信息来装饰 Adriaan Moors 的答案。)
自 2.5 以来,高级类型是 Scala 的一部分。
在此之前,Scala 和 Java 一样,直到现在都不允许使用类型构造函数(Java 中的“泛型”)作为类型构造函数的类型参数。例如 trait Monad [M[_]] 是不可能的。在 Scala 2.5 中,类型系统已通过在更高级别上对类型进行分类的能力进行了扩展(称为类型构造函数多态性)。这些分类称为种类。 (图片来自更高类型的泛型) 结果是,类型构造函数(例如 List)可以与类型构造函数的类型参数位置中的其他类型一样使用,因此它们成为自 Scala 2.5 以来的第一类类型。 (类似于 Scala 中的一等值函数)。在支持更高类型的类型系统的上下文中,我们可以区分正确的类型,如 Int 或 List[Int] 与 List 等一阶类型和更高类型的类型,如 Functor 或 Monad(抽象的类型优于抽象的类型)超过类型)。另一方面,Java 的类型系统不支持种类,因此没有“高级种类”的类型。所以这必须在支持类型系统的背景下才能看到。
在 Scala 的情况下,您经常会看到类型构造函数的示例,例如 trait Iterable[A, Container[_]],其标题为“高级类型”,例如在 Scala 中针对泛型程序员的 4.3 节 这有时会产生误导,因为许多人参考将Container作为更高种类的类型而不是Iterable,但更精确的是,使用Container作为Iterable的更高种类(高阶)类型的类型构造函数参数。
Int
和 Char
等普通类型的 kind,其实例是值,是 *
。像 Maybe
这样的一元类型构造函数是 * -> *
;像 Either
这样的二进制类型构造函数有 (curried) 种类 * -> * -> *
,依此类推。您可以将 Maybe
和 Either
等类型视为类型级函数:它们采用一种或多种类型,并返回一个类型。
如果一个函数的阶大于 1,则该函数是高阶的,其中阶(非正式地)是函数箭头左侧的嵌套深度:
订单 0:1 :: Int
订单 1:chr :: Int -> Char
订单 2:修复 :: (a -> a) -> a,映射 :: (a -> b) -> [a] -> [b]
订单 3: ((A -> B) -> C) -> D
顺序 4: (((A -> B) -> C) -> D) -> E
所以,长话短说,更高种类的类型只是一个类型级别的高阶函数,它抽象了类型构造函数:
订单 0: 整数 :: *
订单 1:也许 :: * -> *
顺序 2:Functor :: (* -> *) -> Constraint—higher-kinded:将一元类型构造函数转换为类型类约束
Functor
从类型构造函数 F
生成正确的类型(嗯,特征,但相同的想法)Functor[F[_]]
。
(* => *) => (* => *)
可以用 Scala 表示吗?如果没有,用任何其他语言?
* ⇒ * ⇒ *
与柯里化的比较非常有帮助。谢谢!
(* ⇒ *) ⇒ (* ⇒ *)
也可以拼写为 (* ⇒ *) ⇒ * ⇒ *
。它可以用 Scala 表示,如 Foo[F[_], T]
。这种类型类似于(在 Haskell 中)newtype Twice f a = Twice (f (f a))
(例如,Twice Maybe Int
≅ Maybe (Maybe Int)
、Twice [] Char
≅ [[Char]]
)或更有趣的东西,例如免费的 monad data Free f a = Pure a | Free (f (Free f a))
。
我会说:更高种类的类型抽象了类型构造函数。例如考虑
trait Functor [F[_]] {
def map[A,B] (fn: A=>B)(fa: F[A]): F[B]
}
这里的 Functor
是“更高种类的类型”(如 "Generics of a Higher Kind" paper 中所用)。它不是像 List
那样的具体(“一阶”)类型构造函数(仅抽象适当的类型)。它抽象了所有一元(“一阶”)类型构造函数(用 F[_]
表示)。
或者换一种说法:在 Java 中,我们有明确的类型构造函数(例如 List<T>
),但我们没有“更高种类的类型”,因为我们不能对它们进行抽象(例如,我们不能编写 { 3} 上面定义的接口——至少不是directly)。
术语“高阶(类型构造器)多态性”用于描述支持“更高种类的类型”的系统。
List<T>
将是一元类型构造函数,因为它显然具有 * -> *
类型。 Jon 的回答中缺少的是,您必须能够抽象出“整个事物”(而不仅仅是 Java 中的第二个 *
)才能将其称为更高种类的类型。
def succ(x: Int) = x+1
引入了“值构造函数”(有关我的意思,请参阅我的其他答案)succ
(没有人将此值称为 succ(x: Int))。以此类推,Functor
是您的答案中定义的(实际上是更高级的)类型。同样,您不应该将其称为 Functor[F[_]]
(什么是 F
?什么是 _
?它们不在范围内!不幸的是,存在主义的语法糖通过使 F[_]
变短而使这里的水域变得混乱F[T forSome {type T}]
)
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.