Scala:理解参数多态性

时间:2014-01-14 14:06:22

标签: scala types parametric-polymorphism

之间有什么区别
def drop1[A](l: List[A]) = l.tail

def drop1(l: List[Int]) = l.tail

提供的用法类似于

drop1(List(1,2,3))

何时应该使用其中一个,为什么?虽然我能理解第二个例子,但我并不真正理解第一个例子的目的。

4 个答案:

答案 0 :(得分:7)

真的非常简单。您的第一个示例是指泛型的概念。

泛型有一个简单的目标,即使某些方法泛型,例如非类型依赖。

让我们看看这个简单的例子。假设我想为drop1编写List方法。

我可以为每种类型写一个:(慢,重复):

def drop1(l: List[Int]): List[Int] = l.tail // this only works for Int

def drop1(l: List[String]): List[String] = l.tail // this only works for String 

您可以看到如何为每种类型编写上述内容。为了克服这个问题,你有一些泛型:

def drop1[A](l: List[A]): List[A] = l.tail // this works for any given type.

基本上说:无论List中包含什么类型,给我尾巴。 我不需要为几乎无限多种类型编写成千上万的{{​​1}}变体,而只需编写一个。

现在在Scala中,您的实现最好用:

drop1

重命名众所周知的库方法通常也是一个坏主意。 implicit class ListOps[A](val l: List[A]) extends AnyVal { def drop1: List[A] = l match { case head :: tail => tail case Nil => Nil } } // you can now have List(1, 2, 3).drop1 操作不安全,tail是安全的。你所造成的一切都是混乱,因为有一种默认的drop方法。

drop

答案 1 :(得分:3)

简而言之 - 某些操作不依赖于特定类型,可以抽象化。计算苹果和计算橙子基本上是相同的操作。如果您要重用算法,那么抽象某些类型而不是编写

会更聪明
def countOranges(xs: List[Orange]) = { some code } 
def countApples(xs: List[Apple]) = { the very same code }

答案 2 :(得分:0)

我来晚了一点,如果您对Java泛型有一个了解,可以在这里进行类比:-

Java ->通用类的对象可以在方法参数中传递。

class Test<T> {
    // An object of type T is declared
    T obj;
    Test(T obj) {  this.obj = obj;  }  // constructor
    // some other methods in class 
}

Test<String> testobj = new Test<String>();

public void function(testobj){ 
// do something with testobj 
}

Scala ->通用参数函数在Scala中的工作方式相同。在这里,[A]在scala中定义了通用类型

def drop1[A](l: List[A]) = l.tail

以上功能的使用:-

scala>drop1(List(1,2,3))   // output List(2, 3)
scala>drop1(List(1.0,2.0,3.0)) // output List(2.0, 3.0)
scala>drop1(List('a','b','c'))  // output List(b, c)

说明:-只要传递任何类型的List,它就可以像超级按钮一样工作。语法如下:-

def function[Type](param:Type):Type = {do something}

答案 3 :(得分:0)

url(r'^(%s)?$' % '|'.join(routes), TemplateView.as_view(template_name='index.html'))