简体   繁体   English

带有类型参数的Scala List

[英]Scala List with type parameter

I had a problem coding a function called head , that basically replace the head elements with another for the List invoking it: 我在编写一个名为head的函数时遇到了问题,它基本上用另一个函数替换头元素,用于调用它的List:

List(1,2,3,4).head(4) // List(4,2,3,4)

The code is obviously useless, I was just trying to have fun with Scala. 代码显然没用,我只是想和Scala一起玩。 This is the code: 这是代码:

sealed trait List[+A]{
  def tail():List[A]
  def head[A](x:A):List[A]
}

object Nil extends List[Nothing]{
  def tail() = throw new Exception("Nil couldn't has tail")
  def head[A](x:A): List[A] = List(x)
}

case class Cons[+A](x :A, xs: List[A]) extends List[A]{
  def tail():List[A] = xs
  def head[A](a:A): List[A] = Cons(a,xs)
}

object List{
  def apply[A](as:A*):List[A] = {
    if (as.isEmpty) Nil
    else Cons(as.head,apply(as.tail: _*))
  }
}

Cons(1,Cons(2,Nil)) == List(1,2)
Cons(1,Cons(2,Cons(3,Cons(4,Nil)))).tail()
List(1,2,3,4,5,6,7).tail()
List(1,2,3,4).head(4)

It doesn't not compile and I have this error: 它没有编译,我有这个错误:

Error:(11, 39) type mismatch;
found   : A$A318.this.List[A(in class Cons)]
required: A$A318.this.List[A(in method head)]
 def head[A](a:A): List[A] = Cons(a,xs)

Could you explain why, please? 你能解释一下原因吗?

Regards. 问候。

Your problem is that your head method is taking another type A , therefore inside that scope the compiler takes those A s as different, ie, the A defined in the trait is shadowed by the A in head[A] . 你的问题是你的head方法正在采用另一种类型A ,因此在该范围内,编译器将那些A s视为不同,即,特征中定义的Ahead[A]A遮蔽。

Also, your head method is taking a covariant element of type A in a contravariant position, so you can't define head as such. 此外,你的head方法是在逆变位置中采用A型的协变元素,因此你不能像这样定义head

What you can do is defining your head as: 您可以做的是将您的head定义为:

def head[B >: A](x: B): List[B]

Hence, you get: 因此,你得到:

object S {
    sealed trait List[+A] {
        def tail(): List[A]
        def head[B >: A](x: B): List[B]
    }

    case object Nil extends List[Nothing] {
        def tail() = throw new Exception("Nil doesn't have a tail")
        def head[B >: Nothing](x: B): List[B] = Cons(x, Nil)
    }

    case class Cons[+A](x: A, xs: List[A]) extends List[A] {
      def tail(): List[A] = xs
      def head[B >: A](a: B): List[B] = Cons(a, xs)
    }

    object List {
      def apply[A](as: A*): List[A] = {
        if (as.isEmpty) Nil
        else Cons(as.head, apply(as.tail: _*))
      }
    }
}

Testing this on the REPL: 在REPL上测试:

scala> :load test.scala
Loading test.scala...
defined object S

scala> import S._
import S._

scala> Nil.head(1)
res0: S.List[Int] = Cons(1,Nil)

scala> Cons(1, Nil).head(4)
res1: S.List[Int] = Cons(4,Nil)

You method head does not need a type parameter, since you already have one defined in the class definition and that is exactly the type you want head to receive (if you want head to create a list of the same type of the original). 方法头不需要类型参数,因为您已经在类定义中定义了一个类型参数,而这正是您希望头部接收的类型(如果您希望头部创建相同类型的原始列表)。

The error you get is because A is two different types in the context of the method head (the one from the method and the other from the class). 您得到的错误是因为A是方法头的上下文中的两种不同类型(来自方法的那个和来自类的另一个)。

The definition for head should be: 头部的定义应该是:

def head(x:A):List[A]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM