Scala 什么';这两者之间的区别是什么;“通用类型”;及;“高级类”类型;?

Scala 什么';这两者之间的区别是什么;“通用类型”;及;“高级类”类型;?,scala,generics,type-systems,higher-kinded-types,Scala,Generics,Type Systems,Higher Kinded Types,我发现自己真的无法理解“泛型”和“高级类型”之间的区别 Scala代码: trait Box[T] 我定义了一个名为Box的trait,它是一个接受参数类型T的类型构造函数。(这句话对吗?) 我可否说: Box是一种通用类型 Box是一种更高级的类型 以上都不正确 当我与同事讨论代码时,我经常在“泛型”和“高级类型”之间挣扎来表达它。高级类型和“泛型”之间没有区别 Box是“结构”或“上下文”,并且T可以是任何类型 因此,T在英语意义上是通用的。。。我们不知道会是什么,也不在乎,因为我们不会直

我发现自己真的无法理解“泛型”和“高级类型”之间的区别

Scala代码:

trait Box[T]
我定义了一个名为
Box
trait
,它是一个接受参数类型
T
的类型构造函数。(这句话对吗?)

我可否说:

  • Box
    是一种通用类型
  • Box
    是一种更高级的类型
  • 以上都不正确

  • 当我与同事讨论代码时,我经常在“泛型”和“高级类型”之间挣扎来表达它。

    高级类型和“泛型”之间没有区别

    Box
    是“结构”或“上下文”,并且
    T
    可以是任何类型

    因此,
    T
    在英语意义上是通用的。。。我们不知道会是什么,也不在乎,因为我们不会直接在
    t
    上操作


    C#也将其称为泛型。我怀疑他们之所以选择这种语言是因为它的简单性(为了不吓跑人们)。

    现在回答可能太晚了,你现在可能已经知道区别了,但我回答这个问题只是为了提供另一种观点,因为我不太确定格雷格所说的是否正确。泛型比高级类型更通用。许多语言,如Java和C,都有泛型,但很少有更高级的类型

    要回答您的特定问题,可以,
    Box
    是一个带有类型参数
    T
    的类型构造函数。您也可以说它是泛型类型,尽管它不是更高级的类型。下面是一个更广泛的答案

    这是维基百科对泛型编程的定义:

    泛型编程是一种计算机编程风格,在这种编程风格中,算法是按照稍后指定的类型编写的,然后在需要时,针对作为参数提供的特定类型实例化这些类型。这种方法由ML在1973年首创,它允许编写通用函数或类型,这些函数或类型在使用时只在它们所操作的类型集中有所不同,从而减少了重复

    假设您这样定义
    Box
    。它包含某种类型的元素,并有一些特殊的方法。它还定义了一个
    map
    函数,类似于
    Iterable
    Option
    ,因此您可以将包含整数的框转换为包含字符串的框,而不会丢失
    box
    具有的所有特殊方法

    案例分类框(元素:任意){
    …一些特殊的方法
    定义映射(f:Any=>Any):Box=Box(f(elem))
    }
    val boxedNum:Box=Box(1)
    val extractedNum:Int=boxedString.elem.asInstanceOf[Int]
    val-boxedString:Box=boxedNum.map(u.toString)
    val extractedString:String=boxedString.elem.asInstanceOf[String]
    
    如果
    Box
    是这样定义的,您的代码会变得非常难看,因为所有对
    asInstanceOf
    的调用,但更重要的是,它不是类型安全的,因为所有东西都是Any

    这就是泛型可以发挥作用的地方。假设我们这样定义
    Box

    case class Box[A](elem: A) {
      def map[B](f: A => B): Box[B] = Box(f(elem))
    }
    
    然后,我们可以使用
    map
    功能来处理各种事情,比如更改
    框中的对象,同时确保它在
    框中。在这里,不需要使用
    asInstanceOf
    ,因为编译器知道
    框的类型以及它们所包含的内容(甚至不需要类型注释和类型参数)

    泛型基本上允许您抽象不同的类型,允许您使用
    Box[Int]
    Box[String]
    作为不同的类型,即使您只需要创建一个
    Box


    但是,假设您不能控制这个
    类,它的定义仅仅是

    case class Box[A](elem: A) {
      //some special methods, but no map function
    }
    
    假设您使用的这个API还定义了自己的
    选项
    列表
    类(都接受表示元素类型的单个类型参数)。现在您希望能够映射所有这些类型,但由于您自己无法修改它们,因此必须定义一个隐式类来为它们创建扩展方法。让我们为扩展方法添加一个隐式类
    Mappable
    ,以及一个类型类
    Mapper

    trait Mapper[C[_]] {
      def map[A, B](context: C[A])(f: A => B): C[B]
    }
    
    implicit class Mappable[C[_], A](context: C[A])(implicit mapper: Mapper[C]) {
      def map[B](f: A => B): C[B] = mapper.map(context)(f)
    }
    
    可以这样定义隐式映射器

    implicit object BoxMapper extends Mapper[Box] {
      def map[B](box: Box[A])(f: A => B): Box[B] = Box(f(box.elem)) 
    }
    implicit object OptionMapper extends Mapper[Option] {
      def map[B](opt: Option[A])(f: A => B): Option[B] = ???
    }
    implicit object ListMapper extends Mapper[List] {
      def map[B](list: List[A])(f: A => B): List[B] = ???
    }
    //and so on
    
    并使用它,就好像
    选项
    列表
    等一直都有
    映射
    方法一样

    这里,
    Mappable
    Mapper
    是更高级的类型,而
    Box
    Option
    List
    是一级类型。它们都是泛型类型和类型构造函数<但是,code>Int
    String
    是正确的类型。以下是它们的(类型与类型的关系就像类型与值的关系一样)

    类型构造函数在某种程度上类似于函数(有时称为值构造函数)。正确的类型(种类
    *
    )类似于简单值。它是一种具体的类型,可以用于返回类型、变量类型等。您可以直接说
    val x:Int
    ,而不传递
    Int
    任何类型参数

    一阶类型(种类
    *->*
    )类似于一个看起来像
    Any=>Any
    的函数。它不是接受一个值并给你一个值,而是接受一个类型并给你另一个类型。如果不给一阶类型提供类型参数(
    val x:List[Int]
    works),则无法直接使用一阶类型(
    val x:List[Int]
    works)。这是泛型所做的——它允许你抽象类型并创建新类型(JVM只是在运行时删除这些信息,但是像C++这样的语言确实生成了新的类和函数)。
    Mapper
    中的类型参数
    C
    也是此类参数。下划线类型参数(也可以使用somethin
    implicit object BoxMapper extends Mapper[Box] {
      def map[B](box: Box[A])(f: A => B): Box[B] = Box(f(box.elem)) 
    }
    implicit object OptionMapper extends Mapper[Option] {
      def map[B](opt: Option[A])(f: A => B): Option[B] = ???
    }
    implicit object ListMapper extends Mapper[List] {
      def map[B](list: List[A])(f: A => B): List[B] = ???
    }
    //and so on
    
    //To check the kind of a type, you can use :kind in the REPL
    Kind of Int and String: *
    Kind of Box, Option, and List: * -> *
    Kind of Mappable and Mapper: (* -> *) -> *