Scala:丰富集合时键入错误

时间:2014-03-22 16:31:46

标签: scala implicit-conversion scala-collections

所以我正在尝试通过Norvig&罗素的“人工智能,现代方法”作为学习斯卡拉的一种方式。我现在对语言基础有很好的把握,但我仍然发现自己经常“打架”类型系统。

长话短说,广度优先和深度优先搜索算法除了推送/弹出到其底层集合的机制之外是相同的。深度优先将预先添加新的可能性并使用堆栈,而广度优先将追加并使用队列。

为了使我的算法保持不变,我创建了一个名为“GiveGrab”的类型类(我知道,名字很可怕),意图是拉皮条...错误... 使用这些“丰富集合”默认“push(give)和pop-like(抓取)操作。例如,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类型签名的好文章?我通过Scala 2nd Ed编程阅读,但它并没有触及这种类型的体操(要么就是这样,或者我只是错过了它。)

编辑:错别字

1 个答案:

答案 0 :(得分:1)

@PatrykĆwiek提出的不是解决方法,而是实际上您要做的事情:特征M[A]中的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)。