隐式转换- Scala:在充实集合时出现类型错误



所以我正在尝试通过Norvig &Russell的"人工智能,一种现代方法"作为学习Scala的一种方式。在这一点上,我已经很好地掌握了语言基础,但我仍然发现自己经常"与"类型系统"斗争"。

长话短说,广度优先和深度优先的搜索算法是相同的,除了向其底层集合推送/打开的机制。深度优先将添加新的可能性并使用Stack,而宽度优先将添加并使用Queue。

为了保持我的算法不变,我创建了一个名为"GiveGrab"(我知道,可怕的名字)的类型类,目的是拉皮条……呃……用这些"默认的"push (give)和pop (grab)操作来丰富集合。例如,grab会导致对队列调用.dequeue(),对堆栈调用.pop()。

下面是代码的缩写版本:

object Example extends App {
  trait GiveGrab[A, M[A]] {
    def give(x: A*): M[A]
    def grab(): A
  }
  implicit class GiveGrabQueue[T](q: Queue[T]) extends GiveGrab[T,Queue[T]] {
    override def give(x: T*) = q ++= x
    override def grab() = q.dequeue()
  }
  class TestClass[T, X <% GiveGrab[T, Queue[T]]](var storage: X) {}
  val test = new TestClass[Int, Queue[Int]](new Queue[Int]())
}

当试图编译这个,我得到以下错误:

Error:(18, 39) scala.collection.mutable.Queue[T] takes no type parameters, expected: one
  class TestClass[T, X <% GiveGrab[T, Queue[T]]](var storage: X) {}
                                  ^
Error:(13, 67) scala.collection.mutable.Queue[T] takes no type parameters, expected: one
  implicit class GiveGrabQueue[T](q: Queue[T]) extends GiveGrab[T,Queue[T]] {
                                                              ^

也就是说,我花了很多的尝试和错误,甚至达到这一点。我不确定我的特质是否真的应该被输入trait GiveGrab[A, M[A]]trait GiveGrab[A, M[_]]trait GiveGrab[A, M]

错误"没有类型参数,预期:一个"在这一点上对我来说没有很大的意义,只有少数其他帖子关于这个消息(一些与依赖类型有关,一些与Play框架有关)。

有点相关:是否有一篇很好的文章来理解Scala类型签名?我通读了一遍Programming in Scala 2nd edition,但它并没有真正涉及到这种类型的体操(要么是这样,要么是我错过了)

编辑:拼写错误

@PatrykĆwiek提出的不是一个解决方案,但实际上你要做的是:M[A]在trait GiveGrab中定义了一个类型函数。粗略地说,这意味着:M是一种可以应用单个类型参数来产生具体类型的类型。这个参数被称为A纯粹是巧合。以下含义相同:

trait GiveGrab[A,M[MyRandomName]] { ... }

give的定义中,当说M[A]时,实际上使用这个类型函数来创建类型。因此,正如@PatrykĆwiek所说,您应该编写Queue而不是Queue[T]。虽然Queue正是这些类型函数之一,但Queue[T]是一个具体类型,因此不适用于M的定义。

你得到的错误信息确切地说:在M的地方,你应该放一个带参数的类型(如Queue),但你已经放了一个不带参数的类型(在你的情况下是Queue[T],另一个例子是StringInt)。

最新更新