什么是Scala中更高级的kinded类型?

Lut*_*utz 262 generics constructor types scala higher-kinded-types

您可以在网上找到以下内容:

  1. 更高的kinded类型==类型构造函数?

    class AClass[T]{...} // For example, class List[T]
    
    Run Code Online (Sandbox Code Playgroud)

    有人说这是一种更高的kinded类型,因为它抽象了符合定义的类型.

    较高的kinded类型是采用其他类型并构造新类型的类型

    这些虽然也称为类型构造函数.(例如,在Scala编程).

  2. 更高的kinded type == type构造函数,它将类型构造函数作为类型参数?

    更高级别的Generics中,您可以阅读

    ...抽象类型抽象的类型("更高级的类型")......"

    这表明

    class XClass[M[T]]{...} // or
    
    trait YTrait[N[_]]{...} // e.g. trait Functor[F[_]]
    
    Run Code Online (Sandbox Code Playgroud)

    是一种更高级的类型.

因此,考虑到这一点,很难区分类型构造函数,更高的kinded类型类型构造函数,它将类型构造函数作为类型参数,因此上面的问题.

Adr*_*ors 270

让我通过一些消除歧义来弥补一些混乱.我喜欢用价值水平的类比来解释这一点,因为人们往往更熟悉它.

类型构造函数是一种类型,您可以将其应用于类型参数以"构造"类型.

值构造函数是可以应用于值参数以"构造"值的值.

值构造函数通常称为"函数"或"方法".这些"构造函数"也被称为"多态"(因为它们可用于构造具有不同"形状"的"东西")或"抽象"(因为它们抽象了不同多态实例之间的变化).

在抽象/多态的上下文中,一阶指的是抽象的"单一使用":你抽象一次类型,但该类型本身不能抽象任何东西.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]})#?
Run Code Online (Sandbox Code Playgroud)

使用的类定义为:

class String
class List[T]
class Functor[F[_]]
Run Code Online (Sandbox Code Playgroud)

为了通过定义类来避免间接,你需要以某种方式表达匿名类型函数,这些函数不能直接在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
Run Code Online (Sandbox Code Playgroud)

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

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

  • Adriaan的"类型构造函数多态性"一文现在http://adriaanm.github.com/research/2010/10/06/new-in-scala-2.8-type-constructor-inference/ (4认同)

Lut*_*utz 98

(这个答案试图用一些图形和历史信息来装饰Adriaan Moors的答案.)

自2.5以来,较高的kinded类型是Scala的一部分.

  • 在Scala之前,作为Java直到现在,不允许使用类型构造函数(Java中的"generics")作为类型构造函数的类型参数.例如

     trait Monad [M[_]]
    
    Run Code Online (Sandbox Code Playgroud)

    是不可能的.

    在Scala 2.5中,通过在更高级别上对类型进行分类的能力(称为类型构造函数多态性)扩展了类型系统.这些分类称为种类.

    类型和种类的实现,**派生**来自 (图片来源于更高级别的泛型)

    结果是,类型构造函数(例如List)可以像类型构造函数的类型参数位置中的其他类型一样使用,因此它们自Scala 2.5起成为第一类类型.(类似于Scala中的第一类值的函数).

    在一种类型的系统中支持更高种上下文中,我们可以区分合适类型,种类等IntList[Int]从第一阶类型,如List类型更高的种FunctorMonad(类型的抽象以上类型的抽象以上类型).

    另一方面Java的类型系统不支持种类,因此没有"更高类型"的类型.

    所以这必须在支持型系统的背景下看到.

  • 在Scala的情况下,您经常会看到类似构造函数的示例

     trait Iterable[A, Container[_]]
    
    Run Code Online (Sandbox Code Playgroud)

    标题为"更高级的类型",例如在通用程序员的Scala中,第4.3节

    这有时是误导性的,因为许多人Container称之为更高级的类型而不是Iterable,但更准确的是,

    这里使用Container更高kinded(更高阶)类型的as类型构造函数参数Iterable.


Jon*_*rdy 75

像和的那种普通类型,其实例是值,是.像一般的类型构造函数是这样的; 二元类型构造函数,如has(curried)kind ,等等.您可以查看类型和类型级别函数:它们采用一种或多种类型,并返回一种类型.IntChar*Maybe* -> *Either* -> * -> *MaybeEither

如果函数的顺序大于1,则函数为高阶函数,其中顺序是(非正式地)函数箭头左侧的嵌套深度:

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

所以,长话短说,一个更高级的类型只是一个类型级的高阶函数.

  • 订单0: Int :: *
  • 订单1: Maybe :: * -> *
  • 顺序2:Functor :: (* -> *) -> Constraint-higher-kinded:将一元类型构造函数转换为类型类约束


Lan*_*dei 33

我会说:一个更高的kinded类型抽象类型构造函数.例如考虑

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

Functor是一种"更高级的类型"(用于"更高级别的泛型"论文).它不是具体的("一阶")类型构造函数List(仅对适当的类型进行抽象).它抽象所有一元("一阶")类型构造函数(如表示F[_]).

或者List<T>换一种说法:在Java中,我们有明确的类型构造函数(例如),但我们没有"更高级的类型",因为我们不能对它们进行抽象(例如,我们不能编写Functor上面定义的接口 -至少不是直接).

术语"高阶(类型构造函数)多态性"用于描述支持"更高级别的类型"的系统.

  • 是.根据Jon的回答(据我所知),Java中的List <T>`将是一个一元类型的构造函数,因为它显然有一种`* - >*`.在Jon的回答中缺少的是你必须能够抽象出"整个事物"(而不仅仅是在Java中的第二个`*`),以便将其称为更高的kinded类型. (3认同)
  • 一般来说,在这里区分定义和参考是很重要的.定义`def succ(x:Int)= x + 1`引入了"值构造函数"(请参阅​​我的另一个答案,我的意思)`succ`(没有人会将此值称为succ(x: INT)).通过类比,"Functor"是你答案中定义的(确实是更高级的)类型.再说一次,你不应该把它称为"Functor [F [_]]`(什么是`F`?什么是`_`?它们不在范围内!不幸的是,存在的语法糖混淆了这里的水域通过使`F [_]`缩写为`F [T forSome {type T}]`) (2认同)

Mar*_*lic 5

Scala REPL 提供了:kind命令

scala> :help kind

:kind [-v] <type>
Displays the kind of a given type.
Run Code Online (Sandbox Code Playgroud)

例如,

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.
Run Code Online (Sandbox Code Playgroud)

:help规定明确的定义,所以我认为这是值得张贴在这里的全部(斯卡拉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.
Run Code Online (Sandbox Code Playgroud)