简体   繁体   English

Scala 中的高级类型是什么?

[英]What is a higher kinded type in Scala?

You can find the following on the web:您可以在 web 上找到以下内容:

  1. 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 ). (例如, 在 Scala 中的编程中)。

  2. Higher kinded type == type constructor which takes type constructor as a type parameter?更高种类的类型 == 类型构造函数,它将类型构造函数作为类型参数?

    In the paper Generics of a Higher Kind , you can read更高种类的论文 Generics 中,您可以阅读

    ... types that abstract over types that abstract over types ('higher-kinded types')..." ...抽象类型的类型抽象类型('高级类型')......“

    which suggests that这表明

    class XClass[M[T]]{...} // or trait YTrait[N[_]]{...} // eg trait Functor[F[_]]

    is a higher kinded type.是高种类型。

So with this in mind, it is difficult to distinguish between type constructor , higher kinded type and type constructor which takes type constructors as type parameter , therefore the question above.因此,考虑到这一点,很难区分类型构造函数更高种类的类型以类型构造函数作为类型参数的类型构造函数,因此上面的问题。

Let me make up for starting some of this confusion by pitching in with some disambiguation.让我通过一些消歧来弥补开始的一些混乱。 I like to use the analogy to the value level to explain this, as people tend to be more familiar with it.我喜欢用价值水平的类比来解释这一点,因为人们往往更熟悉它。

A type constructor is a type that you can apply to type arguments to "construct" a type.类型构造函数是可以应用于类型 arguments 以“构造”类型的类型。

A value constructor is a value that you can apply to value arguments to "construct" a value.值构造函数是可以应用于值 arguments 以“构造”值的值。

Value constructors are usually called "functions" or "methods".值构造函数通常称为“函数”或“方法”。 These "constructors" are also said to be "polymorphic" (because they can be used to construct "stuff" of varying "shape"), or "abstractions" (since they abstract over what varies between different polymorphic instantiations).这些“构造函数”也被称为“多态”(因为它们可用于构造不同“形状”的“东西”)或“抽象”(因为它们抽象了不同多态实例之间的变化)。

In the context of abstraction/polymorphism, first-order refers to "single use" of abstraction: you abstract over a type once, but that type itself cannot abstract over anything.在抽象/多态的上下文中,一阶是指抽象的“一次性使用”:您对一个类型进行一次抽象,但该类型本身不能对任何东西进行抽象。 Java 5 generics are first-order. Java 5 generics 为一阶。

The first-order interpretation of the above characterizations of abstractions are:上述抽象特征的一阶解释是:

A type constructor is a type that you can apply to proper type arguments to "construct" a proper type.类型构造函数是一种可以应用于正确类型 arguments 以“构造”正确类型的类型。

A value constructor is a value that you can apply to proper value arguments to "construct" a proper value.值构造函数是可以应用于正确值 arguments 以“构造”正确值的值。

To emphasize there's no abstraction involved (I guess you could call this "zero-order", but I have not seen this used anywhere), such as the value 1 or the type String , we usually say something is a "proper" value or type.为了强调不涉及抽象(我猜你可以称之为“零阶”,但我没有看到它在任何地方使用过),例如值1或类型String ,我们通常说某物是“正确”值或类型。

A proper value is "immediately usable" in the sense that it is not waiting for arguments (it does not abstract over them).正确的值是“立即可用的”,因为它不等待 arguments(它不抽象它们)。 Think of them as values that you can easily print/inspect (serializing a function is cheating.).将它们视为您可以轻松打印/检查的值(序列化 function 是作弊。)。

A proper type is a type that classifies values (including value constructors), type constructors do not classify any values (they first need to be applied to the right type arguments to yield a proper type).正确的类型是对值进行分类的类型(包括值构造函数),类型构造函数不会对任何值进行分类(它们首先需要应用于正确的类型 arguments 以产生正确的类型)。 To instantiate a type, it's necessary (but not sufficient) that it be a proper type.要实例化一个类型,有必要(但不充分)它是一个正确的类型。 (It might be an abstract class, or a class that you don't have access to.) (它可能是您无权访问的抽象 class 或 class。)

"Higher-order" is simply a generic term that means repeated use of polymorphism/abstraction. “高阶”只是一个通用术语,表示重复使用多态性/抽象。 It means the same thing for polymorphic types and values.对于多态类型和值来说,这意味着同样的事情。 Concretely, a higher-order abstraction abstracts over something that abstracts over something.具体来说,高阶抽象抽象了一些抽象的东西。 For types, the term "higher-kinded" is a special-purpose version of the more general "higher-order".对于类型,术语“higher-kinded”是更一般的“higher-order”的特殊用途版本。

Thus, the higher-order version of our characterization becomes:因此,我们表征的高阶版本变为:

A type constructor is a type that you can apply to type arguments (proper types or type constructors) to "construct" a proper type (constructor).类型构造函数是可以应用于类型 arguments(正确类型或类型构造函数)以“构造”正确类型(构造函数)的类型。

A value constructor is a value that you can apply to value arguments (proper values or value constructors) to "construct" a proper value (constructor).值构造函数是可以应用于值 arguments(正确值或值构造函数)以“构造”正确值(构造函数)的值。

Thus, "higher-order" simply means that when you say "abstracting over X", you really mean it!因此,“高阶”仅仅意味着当你说“对 X 进行抽象”时,你是认真的! The X that is abstracted over does not lose its own "abstraction rights": it can abstract all it wants.被抽象出来的X并没有失去它自己的“抽象权”:它可以抽象它想要的一切。 (By the way, I use the verb "abstract" here to mean: to leave out something that is not essential for the definition of a value or type, so that it can be varied/provided by the user of the abstraction as an argument.) (顺便说一句,我在这里使用动词“抽象”来表示:省略对值或类型的定义不重要的东西,以便抽象的用户可以改变/提供它作为参数.)

Here are some examples (inspired by Lutz's questions by email) of proper, first-order and higher-order values and types:以下是一些正确的、一阶和高阶值和类型的示例(灵感来自 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]})#λ

Where the used classes were defined as:使用的类被定义为:

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

To avoid the indirection through defining classes, you need to somehow express anonymous type functions, which are not expressible directly in Scala, but you can use structural types without too much syntactic overhead (the -style is due to https://stackoverflow.com/users/160378/retronym afaik):为了避免通过定义类的间接性,您需要以某种方式表达匿名类型函数,这些函数在 Scala 中无法直接表达,但您可以使用结构类型而不会产生太多语法开销( 样式是由于https://stackoverflow .com/users/160378/retronym afaik):

In some hypothetical future version of Scala that supports anonymous type functions, you could shorten that last line from the examples to:在支持匿名类型函数的 Scala 的某些假设的未来版本中,您可以将示例中的最后一行缩短为:

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

(On a personal note, I regret ever having talked about "higher-kinded types", they're just types after all, When you absolutely need to disambiguate, I suggest saying things like "type constructor parameter", "type constructor member", or "type constructor alias". to emphasize that you're not talking about just proper types.) (就个人而言,我很遗憾曾经谈论过“高级类型”,它们毕竟只是类型,当您绝对需要消除歧义时,我建议说诸如“类型构造函数参数”,“类型构造函数成员”之类的东西, 或“类型构造函数别名”。强调你不是在谈论正确的类型。)

ps: To complicate matters further, "polymorphic" is ambiguous in a different way, since a polymorphic type sometimes means a universally quantified type, such as Forall T, T => T , which is a proper type, since it classifies polymorphic values (in Scala, this value can be written as the structural type {def apply[T](x: T): T = x} ) ps:为了使事情进一步复杂化,“多态”以不同的方式是模棱两可的,因为多态类型有时意味着普遍量化的类型,例如Forall T, T => T ,这是一个正确的类型,因为它对多态值进行分类(在 Scala 中,这个值可以写成结构类型{def apply[T](x: T): T = x} )

(This answer is an attempt to decorate Adriaan Moors answer by some graphical and historical information.) (这个答案试图通过一些图形和历史信息来装饰 Adriaan Moors 的答案。)

Higher kinded types are part of Scala since 2.5.自 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.在此之前 Scala 和 Java 之前不允许使用类型构造函数(Java 中的“泛型”)作为类型构造函数的类型参数。 eg例如

     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 ).在 Scala 2.5 中,类型系统已通过在更高级别上对类型进行分类的能力进行了扩展(称为类型构造函数多态性)。 These classifications are known as kinds.这些分类称为种类。

    类型和种类属性,**派生于**来自“更高种类的泛型” (Picture derived from Generics of a Higher Kind ) (图片来源于Generics of a Higher Kind

    The consequence is, that type constructor (eg 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.结果是,该类型构造函数(例如List )可以与类型构造函数的类型参数 position 中的其他类型一样使用,因此它们成为自 Scala 2.5 以来的第一个 class 类型。 (Similar to functions which are first class values in Scala). (类似于 Scala 中的第一个 class 值的函数)。

    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).在支持更高种类的类型系统的上下文中,我们可以区分正确的类型,如IntList[Int]等类型与List等一阶类型和更高类型的类型FunctorMonad (抽象的类型优于抽象的类型)超过类型)。

    The type system of Java on the other side does not support kinds and therefore has no types of a "higher kind".另一边的 Java 的类型系统不支持种类,因此没有“更高种类”的类型。

    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在 Scala 的情况下,您经常会看到类型构造函数的示例,例如

     trait Iterable[A, Container[_]]

    with the headline "Higher kinded types", eg in Scala for generic programmers, section 4.3标题为“更高类型的类型”,例如在Scala 中,用于通用程序员,第 4.3 节

    This is sometimes missleading, because many refer to Container as higher kinded type and not Iterable , but what is more precise is,这有时会产生误导,因为许多人将Container称为更高种类的类型而不是Iterable ,但更准确的是,

    the use of Container as type constructor parameter of a higher kinded (higher-order) type here Iterable .在这里使用Container作为更高种类(更高阶)类型的类型构造函数参数Iterable

The kind of ordinary types like Int and Char , whose instances are values, is * .IntChar这样的普通类型,其实例是值,是* The kind of unary type constructors like Maybe is * -> * ;Maybe这样的一元类型构造函数是* -> * binary type constructors like Either have ( curried ) kind * -> * -> * , and so on.Either这样的二进制类型构造函数有 ( curried ) kind * -> * -> *等等。 You can view types like Maybe and Either as type-level functions: they take one or more types, and return a type.您可以将MaybeEither这样的类型视为类型级函数:它们采用一种或多种类型,并返回一个类型。

A function is higher-order if it has an order greater than 1, where the order is (informally) the nesting depth, to the left, of function arrows:如果 function 的阶数大于 1,则它是高阶的,其中阶数(非正式地)是 function 箭头左侧的嵌套深度:

  • Order 0: 1:: Int订单 0: 1:: Int
  • Order 1: chr:: Int -> Char订单 1: chr:: Int -> Char
  • Order 2: fix:: (a -> a) -> a , map:: (a -> b) -> [a] -> [b]订单 2: fix:: (a -> a) -> a , map:: (a -> b) -> [a] -> [b]
  • Order 3: ((A -> B) -> C) -> D订单 3: ((A -> B) -> C) -> D
  • Order 4: (((A -> B) -> C) -> D) -> E顺序 4: (((A -> B) -> C) -> D) -> E

So, long story short, a higher-kinded type is just a type-level higher-order function which abstracts over type constructors:所以,长话短说,更高种类的类型只是类型级别的更高阶 function抽象类型构造函数:

  • Order 0: Int:: *订单 0: Int:: *
  • Order 1: Maybe:: * -> *订单 1: Maybe:: * -> *
  • Order 2: Functor:: (* -> *) -> Constraint —higher-kinded: converts unary type constructors to typeclass constraints顺序 2: Functor:: (* -> *) -> Constraint —higher-kinded:将一元类型构造函数转换为类型类约束

I would say: A higher kinded type abstracts over a type constructor.我会说:更高种类的类型抽象了类型构造函数。 Eg consider例如考虑

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

Here Functor is a "higher kinded type" (as used in the "Generics of a Higher Kind" paper ).这里Functor是一种“更高种类的类型”(如“更高种类的泛型”论文中使用的那样)。 It is not a concrete ("first-order") type constructor like List (which abstracts over proper types only).它不是像List那样的具体(“一阶”)类型构造函数(仅抽象适当的类型)。 It abstracts over all unary ("first-order") type constructors (as denoted with F[_] ).它抽象了所有一元(“一阶”)类型构造函数(用F[_]表示)。

Or to put it in another way: In Java, we have clearly type constructors (eg List<T> ), but we have no "higher kinded types", because we can't abstract over them (eg we can't write the Functor interface defined above - at least not directly ).或者换一种说法:在 Java 中,我们有明确的类型构造函数(例如List<T> ),但是我们没有“更高种类的类型”,因为我们不能对它们进行抽象(例如,我们不能编写上面定义的Functor接口 - 至少不是直接的)。

The term "higher order (type constructor) polymorphism" is used to describe systems that support "higher kinded types".术语“高阶(类型构造器)多态性”用于描述支持“更高种类的类型”的系统。

Scala REPL provides :kind command which Scala REPL 提供:kind命令

scala> :help kind

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

For example,例如,

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.

The :help provides clear definitions so I think it is worth posting it here in its entirety (Scala 2.13.2) :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.

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM