Scala 什么';这两者之间的区别是什么;“通用类型”;及;“高级类”类型;?
我发现自己真的无法理解“泛型”和“高级类型”之间的区别 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在英语意义上是通用的。。。我们不知道会是什么,也不在乎,因为我们不会直
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: (* -> *) -> *