您可以在网上找到以下内容:
更高级的kinded type == type constructor?
class AClass[T]{...} // For example, class List[T]
有人说这是一种更高的kinded类型,因为它 抽象符合定义的类型。
高级类型是采用其他类型并构建新类型的类型
这些也称为类型构造函数。 (例如,在Programming in Scala)。
更高的kinded type == type构造函数,它将类型构造函数作为类型参数?
在论文Generics of a Higher Kind中,您可以阅读
...抽象类型抽象的类型 ('更高级的类型')......“
表明
class XClass[M[T]]{...} // or trait YTrait[N[_]]{...} // e.g. trait Functor[F[_]]
是一种更高级的类型。
因此,考虑到这一点,很难区分类型构造函数,高级类型和类型构造函数,它将类型构造函数作为类型参数,因此上面的问题。
答案 0 :(得分:250)
让我通过一些消除歧义来弥补一些混乱。我喜欢用价值水平的类比来解释这一点,因为人们往往更熟悉它。
类型构造函数是一种类型,您可以将其应用于类型参数以“构造”类型。
值构造函数是一个值,您可以将其应用于值参数以“构造”值。
值构造函数通常称为“函数”或“方法”。这些“构造函数”也被称为“多态”(因为它们可用于构造具有不同“形状”的“东西”)或“抽象”(因为它们抽象了不同多态实例之间的变化)。
在抽象/多态的上下文中,first-order指的是抽象的“单独使用”:你抽象一次类型,但该类型本身不能抽象任何东西。 Java 5泛型是一阶的。
上述抽象表征的一阶解释是:
类型构造函数是一种类型,您可以将其应用于正确的类型参数以“构造”正确的类型。
值构造函数是一个值,您可以将其应用于正确的值参数以“构造”正确的值。
强调没有涉及抽象(我猜你可以称之为“零顺序”,但我没有看到这在任何地方使用过),例如值1
或类型String
,我们通常说某事是“适当的”价值或类型。
正确的值是“可立即使用”,因为它不等待参数(它不会抽象它们)。将它们视为可以轻松打印/检查的值(序列化功能是作弊!)。
正确的类型是对值进行分类的类型(包括值构造函数),类型构造函数不对任何值进行分类(它们首先需要应用于正确的类型参数以生成正确的类型)。要实例化一个类型,必须(但不充分)它是一个合适的类型。 (它可能是一个抽象类,或者您无权访问的类。)
“高阶”只是一个通用术语,意味着重复使用多态/抽象。对于多态类型和值,它意味着相同的事情。具体地说,高阶抽象抽象了抽象某事物的东西。对于类型,术语“更高级的”是更通用的“高阶”的特殊用途版本。
因此,我们的表征的高阶版本变为:
类型构造函数是一种类型,您可以将其应用于类型参数(正确的类型或类型构造函数)以“构造”正确的类型(构造函数)。
值构造函数是可以应用于值参数(正确值或值构造函数)以“构造”正确值(构造函数)的值。
因此,“高阶”只是意味着当你说“抽象X”时,你的确意味着它!被抽象出来的X
并没有失去自己的“抽象权”:它可以抽象出所有想要的东西。 (顺便说一句,我在这里使用动词“abstract”来表示:省略一些对于值或类型的定义不重要的东西,以便它可以由抽象的用户作为参数变化/提供。)
以下是适当的,一阶和更高阶价值和类型的一些示例(受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中,此值可以写为结构类型{def apply[T](x: T): T = x}
)
答案 1 :(得分:92)
(这个答案试图用一些图形和历史信息来装饰Adriaan Moors的答案。)
自2.5以来,较高的kinded类型是Scala的一部分。
在Scala之前,就像Java一样, 不允许使用类型构造函数 (Java中的“泛型”)用作 类型构造函数的类型参数。 e.g。
trait Monad [M[_]]
是不可能的。
在Scala 2.5中,通过分类能力扩展了类型系统 更高级别的类型(称为类型构造函数多态性)。这些 分类被称为种类。
(图片来自Generics of a Higher Kind)
结果是,可以使用该类型构造函数(例如List
)
就像构造函数类型的类型参数位置中的其他类型一样
自Scala 2.5以来,它们成为了一流的类型。 (类似于Scala中第一类值的函数)。
在支持更高类型的类型系统的上下文中,我们可以
区分正确类型,类似Int
或List[Int]
等类型,如List
和更高类型类似{ {1}}或Functor
(抽象类型抽象类型的类型)。
另一方面Java的类型系统不支持种类,因此没有类型 “更高级别”。
所以必须在支持类型系统的背景下看到这一点。
对于Scala,您经常会看到类似构造函数的示例
Monad
标题为“更高级的类型”,例如在Scala for generic programmers, section 4.3
这有时会产生误导,因为很多人将 trait Iterable[A, Container[_]]
称为更高级别的而不是Container
,但更准确的是,
使用
Iterable
作为更高级别(更高阶)类型的类型构造函数参数Container
。
答案 2 :(得分:68)
Int
和Char
等普通类型kind,其实例为值,为*
。像Maybe
这样的一元类型构造函数是* -> *
;像Either
这样的二进制类型构造函数具有(curried)种类* -> * -> *
,依此类推。您可以将Maybe
和Either
等类型视为类型级函数:它们采用一种或多种类型,并返回一种类型。
如果订单大于1,则函数为高阶,其中顺序是(非正式地)功能箭头左侧的嵌套深度:
1 :: Int
chr :: Int -> Char
fix :: (a -> a) -> a
,map :: (a -> b) -> [a] -> [b]
((A -> B) -> C) -> D
(((A -> B) -> C) -> D) -> E
所以,长话短说,高级类型只是一种类型级别的高阶函数。
Int :: *
Maybe :: * -> *
Functor :: (* -> *) -> Constraint
- 更高知名度:将一元类型构造函数转换为类型类约束答案 3 :(得分:31)
我会说:一个更高的kinded类型抽象类型构造函数。例如。考虑
trait Functor [F[_]] {
def map[A,B] (fn: A=>B)(fa: F[A]): F[B]
}
这里Functor
是“更高级的类型”(如“更高类型的泛型”论文中所使用的)。它不是具体的(“一阶”)类型构造函数,如List
(仅对适当的类型进行抽象)。它抽象了所有一元(“一阶”)类型构造函数(用F[_]
表示)。
或者换句话说:在Java中,我们有明确的类型构造函数(例如List<T>
),但我们没有“更高级的类型”,因为我们无法对它们进行抽象(例如我们可以不要写上面定义的Functor
接口 - 至少不是directly)。
术语“高阶(类型构造函数)多态”用于描述支持“更高级别的类型”的系统。
答案 4 :(得分:2)
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.