【发布时间】:2014-03-22 16:31:45
【问题描述】:
所以我正在尝试通过 Norvig & Russell 的“人工智能,一种现代方法”作为学习 Scala 的一种方式。在这一点上,我已经很好地掌握了语言基础知识,但我仍然发现自己经常与类型系统“战斗”。
长话短说,广度优先和深度优先搜索算法除了推送/弹出到其底层集合的机制外是相同的。深度优先将追加新的可能性并使用堆栈,而广度优先将追加并使用队列。
为了保持我的算法不变,我创建了一个名为“GiveGrab”(我知道,可怕的名字)的类型类,目的是用这些“默认" push (give) 和 pop-like (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 Ed,但它并没有真正涉及到这种类型的体操(或者我只是错过了它。)
编辑:错别字
【问题讨论】:
-
如果您将定义更改为
extends GiveGrab[T, Queue]和class TestClass[T, X <% GiveGrab[T, Queue]],它将正常工作。我不完全确定为什么这种表示法有效(可能是因为M[_]符合已经参数化的类型Queue[T]),因此它只是一个评论而不是答案,但有人对更高的知识有更多的了解Scala 中的 -kinded 类型可能会在这里有所启发。 -
刚刚测试过——正如你所说——它似乎工作正常。至少在我们等待有人解释原因时,我有一个解决方法。 :) 谢谢帕特里克!
标签: scala implicit-conversion scala-collections