简体   繁体   English

Scala泛型:类型不匹配

[英]Scala generic: type mismatch

In the purpose of learning, I would like to understand how "::" class is working. 在学习的目的,我想了解“::”类是如何工作的。
So I decided to create my own but instead of calling it "::" I want to call it ":++:" 所以我决定创建自己的,但不是称它为“::”我想称之为“:++:”

From List.scala source code, the University of Helsinki and Programming In Scala 2nd edition (Chapter 22) I should write: List.scala源代码, 赫尔辛基大学和Scala编程第2版(第22章)我应该写:

abstract class List[+A] {
    def isEmpty: Boolean
    def head: A
    def tail: List[A]
}

final case class :++:[A](head: A, tail: List[A]) extends List[A] {
  override def isEmpty: Boolean = false
}


I can create "::" objects 我可以创建“::”对象

new ::(1, List(2)) 新::( 1,清单(2))

But I can't create my ":++:" objects: 但我无法创建我的“:++:”对象:

new :++:(1, List(2))
<console>:12: error: type mismatch;
found   : List[Int]
required: List[?]
            new :++:(1, List(2))

Where is my mistake? 我的错误在哪里?

Annotating the :++: type parameter gives you a hint: 注释:++: type参数为您提供了一个提示:

scala> new :++:[Int](1, List(2))
<console>:11: error: type mismatch;
 found   : scala.collection.immutable.scala.collection.immutable.List[Int]
 required: List(in object $iw)[Int]
              new :++:[Int](1, List(2))
                                   ^

The :++: constructor expects one of your custom List[A] instances, but you give it a normal Scala List(1) . :++:构造函数需要一个自定义List[A]实例,但是你给它一个普通的Scala List(1)

But you currently have no way to create an instance of your list (other than having a null tail). 但是你目前无法创建列表的实例(除了有一个null尾)。 If you add an equivalent of Nil , then you are all good: 如果你添加相当于Nil ,那么你们都很好:

case object Empty extends List[Nothing] { 
  def head = ???
  def isEmpty = true
  def tail = ???
}

And then you can create a :++: : 然后你可以创建一个:++: ::

scala> val a = new :++:[Int](1, Empty)
a: :++:[Int] = :++:(1,Empty)

scala> val b = new :++:(2, a)
b: :++:[Int] = :++:(2,:++:(1,Empty))

In addition to gourlaysama's answer which explains why your definition is shadowed by the built-in List , I'd like to drop a few hints. 除了gourlaysama的答案 ,它解释了为什么你的定义被内置List所掩盖,我想提一些提示。

  1. Per answer above, you should also add the Empty or CNil case object for the 'empty' list. 根据上面的答案,您还应该为“空”列表添加EmptyCNil案例对象。
  2. If you check the sources again, you'll find 'cons' method in the built-in List , similar to one below: 如果再次检查源,您将在内置List找到'cons'方法,类似于下面的方法:

sealed abstract class ConsList[+A] {
    (...)
    def :++:[B >: A](x : B) : ConsList[B] = new :++:(x, this)
}

It allows you to create the list using infix notation: 它允许您使用中缀表示法创建列表:

val b = 2 :++: 4 :++: 7 :++: CNil

And finally, you can create a companion object for easier list creation: 最后,您可以创建一个伴随对象,以便更轻松地创建列表:

object ConsList {
  def apply[A](xs : A*) = {
    xs.foldRight(CNil : ConsList[A])((el, l) => el :++: l)
  }
}

Which means that you can now create val c = ConsList(2, 4, 7) which will be equivalent to b above, and also equivalent to :++:(2, :++:(4, :++:(7, CNil))) 这意味着你现在可以创建val c = ConsList(2, 4, 7) ,它等同于上面的b ,也相当于:++:(2, :++:(4, :++:(7, CNil)))

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

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