首页 文章

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

提问于
浏览
228

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

  • Higher kinded type == type constructor?

class AClass [T] //例如,类List [T]

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

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

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

  • Higher kinded type == type constructor which takes type constructor as a type parameter?

在论文Generics of a Higher Kind中,您可以阅读

...抽象类型抽象的类型('更高级的类型')......“

这表明

class XClass [M [T]] //或

特质YTrait [N [_]] //例如特质函子[F [_]]

是一种更高级的类型 .

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

4 回答

  • 241

    kind的普通类型如 IntChar ,其实例是值,是 * . 像 Maybe 这样的一元类型构造函数是 * -> * ;像 Either 这样的二进制类型构造函数有(curried)类 * -> * -> * ,依此类推 . 您可以将 MaybeEither 等类型视为类型级函数:它们采用一种或多种类型,并返回一个类型 .

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

    • 订单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

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

    • 订单0: Int :: *

    • 订单1: Maybe :: * -> *

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

  • 66

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

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

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

    是不可能的 .

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

    Type and  kind realtion, derived from "Generics of a Higher Kind"
    (图片来源于Generics of a Higher Kind

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

    在支持更高类型的类型系统的上下文中,我们可以区分 proper types ,像 IntList[Int] 这样的类型,如 Listtypes of a higher kind ,如 FunctorMonad (抽象类型抽象类型的类型) .

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

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

    • 对于Scala,您经常会看到类似构造函数的示例
    trait Iterable[A, Container[_]]
    

    Headers 为"Higher kinded types",例如在Scala for generic programmers, section 4.3

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

    使用Container作为更高级别(更高阶)类型的类型构造函数参数,这里是Iterable .

  • 28

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

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

    这里 Functor 是"higher kinded type"(在"Generics of a Higher Kind"论文中使用) . 它不是具体的("first-order")类型构造函数,如 List (仅对适当的类型进行抽象) . 它抽象了所有一元("first-order")类型构造函数(用 F[_] 表示) .

    或者换句话说:在Java中,我们有明确的类型构造函数(例如 List<T> ),但我们没有"higher kinded types",因为我们可以't abstract over them (e.g. we can't写上面定义的 Functor 接口 - 至少不是directly) .

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

  • 87

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

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

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

    在抽象/多态的上下文中,first-order指的是抽象的“单独使用”:你在一个类型上抽象一次,但那个类型本身不能抽象出任何东西 . Java 5泛型是一阶的 .

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

    类型构造函数是一种类型,您可以将其应用于正确的类型参数以“构造”正确的类型 . 值构造函数是一个值,您可以将其应用于正确的值参数以“构造”正确的值 .

    为了强调没有涉及抽象(我想你可以称之为"zero-order",但我没有看到这在任何地方使用过),例如值 1 或类型 String ,我们通常说的是"proper"值或类型 .

    正确的值是“可立即使用”,因为它不等待参数(它不会抽象它们) . 将它们视为可以轻松打印/检查的值(序列化功能是作弊!) .

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

    “高阶”只是一个通用术语,意味着重复使用多态/抽象 . 对于多态类型和值,它意味着相同的事情 . 具体地说,高阶抽象抽象了抽象某事物的东西 . 对于类型,术语“高级”是更通用的“高阶”的特殊用途版本 .

    因此,我们的表征的高阶版本变为:

    类型构造函数是一种类型,您可以将其应用于类型参数(正确的类型或类型构造函数)以“构造”正确的类型(构造函数) . 值构造函数是可以应用于值参数(正确值或值构造函数)以“构造”适当值(构造函数)的值 .

    因此,"higher-order"只是意味着当你说"abstracting over X"时,你真的是这个意思!抽象的 X 并没有丢失它自己的"abstraction rights":它可以抽象它想要的一切 . (顺便说一句,我在这里使用动词"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中表达,但是你可以使用结构类型而没有太多的语法开销( -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:为了使问题进一步复杂化,"polymorphic"以不同的方式模糊不清,因为多态类型有时意味着一种普遍量化的类型,例如 Forall T, T => T ,这是一种正确的类型,因为它对多态值进行了分类(在Scala中,这个值可以写成作为结构类型 {def apply[T](x: T): T = x}

相关问题