所以我正在尝试通过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编程阅读,但它并没有触及这种类型的体操(要么就是这样,或者我只是错过了它。)
编辑:错别字
答案 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]
在您的情况下,另一个例子是String
或Int
)。