Scala中的高级类型是什么?

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

  1. < p > 更高类型的类型==类型构造函数?

    class AClass[T]{...} // For example, class List[T]
    
    有人说这是一个高级类型,因为它 对符合定义的类型进行抽象

    高级类型是接受其他类型并构造新类型的类型

    这些也被称为类型构造函数。(例如,在Scala编程中)

  2. < p > 更高类型的类型==类型构造函数将类型构造函数作为类型参数?

    在论文高等类的泛型中,你可以读到

    < p >…对类型进行抽象的类型对类型进行抽象的类型 (“高等类型”)……" < / p >

    这表明

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

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

76335 次浏览

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

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

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

所以,长话短说,higher-kinded类型只是一个类型级的高阶函数摘要在类型构造函数:

  • Order 0: Int :: *
  • 顺序1:Maybe :: * -> *
  • 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接口-至少不能编写直接)。

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

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

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

    在此之前,Scala,作为Java直到现在, 不允许使用类型构造函数 (Java中的“泛型”)被用作 类型构造函数的类型参数。例如< / p >
     trait Monad [M[_]]
    

    不可能。

    在Scala 2.5中,类型系统扩展了分类功能 类型在更高的级别(称为类型构造函数多态性)。这些

    类型和种类的关系,**源自 (图片来自高等类的泛型)

    结果是,类型构造函数(例如List)可以被使用 就像其他类型在类型形参中的类型构造函数位置一样 从Scala 2.5开始,它们就成为了第一类类型。(类似于Scala中作为第一类值的函数) 在支持更高类型的类型系统的上下文中,我们可以 将适当的类型,类型如IntList[Int]与一阶类型如List更高层次的类型FunctorMonad(类型抽象于类型抽象于类型)区分开来 另一端Java的类型系统不支持类型,因此没有类型

    因此,这必须在支持类型系统的背景下看待。 < / p > 在Scala中,你经常会看到类似的类型构造函数的例子

     trait Iterable[A, Container[_]]
    

    标题为“高级类型”,例如在面向泛型程序员的Scala,第4.3节

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

    使用Container作为更高类型(更高阶)类型的类型构造函数参数在这里Iterable

    李< /引用> < / >

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

类型构造函数是一种类型,你可以将它应用到“构造”的类型参数中。一个类型。

值构造函数是一个值,你可以把它应用到“构造”的值参数中。一个值。

值构造函数通常被称为“函数”;或“;methods"。这些“constructors"也被称为“多态的”;(因为它们可以用来构造“stuff”;具有不同的“形状”),或“抽象”;(因为它们抽象了不同的多态实例化之间的差异)。

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

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

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

值构造函数是一个值,你可以把它应用到正确的值参数中。一个合适的值。

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

合适的值是“立即可用”;在这个意义上,它不等待论证(它不抽象论证)。可以把它们看作是可以轻松打印/检查的值(序列化函数是欺骗!)

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

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

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

类型构造函数是一种类型,您可以将其应用于类型参数(适当的类型或类型构造函数)。合适的类型(构造函数)。

值构造函数是一个值,你可以把它应用到值参数(合适的值或值构造函数)到“构造”。一个合适的值(构造函数)。

因此,“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中不能直接表达,但你可以使用结构类型,而没有太多的语法开销(-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.