我是Scala的新手,需要一些帮助来解决编译错误:
[error] .../traversals /traversals.scala:120: type mismatch;
[error] found : Traversable[Tree]
[error] required: Traversable[Node]
[error] Note: Tree >: Node, but trait Traversable is invariant in type T.
[error] You may wish to define T as -T instead. (SLS 4.5)
[error] println ("Sorted " + sorted (tree2) (monadApp,inOrder));
[error] ^
[error] one error found
我很抱歉MWE那么久了,但是当我想写一些利用它们的例子时,我以一种天真的方式将一些类型的类从Haskell转换为Scala。
我不完全理解这个问题,但似乎我的Traversable
特征不允许T
被某个子类型或具体实例inOrder
或函数{替换{1}}使用该实例。根据编译器的建议,我尝试在sorted
特征的-
前面添加一些T
,Traversable
定义前面的Tree
或inOrder
前面的T
,但它没有帮助。
sorted
答案 0 :(得分:5)
问题是您有两种不同的类型:Traversable[Node]
和Traversable[Tree]
。这来自Haskell的ADT翻译。在Haskell中Node
和Empty
都是Tree
,而在Scala中,它们是Tree
的子类型,这会导致方差的概念发挥作用:给定A
B
的子类型,T[A]
的子类型为T[B]
?
如果我们查看函数X => Y
的类型,我们会看到它被声明为Function1[-X, +Y]
,即X
中的逆变和{{1}中的协变}。这意味着需要Y
并返回Tree
的函数是一个函数的子类型,它接受Node
并返回Node
。例如:
Tree
函数def f[T](n: Node[T])(func: Node[T] => Tree[T]): Tree = func(n)
def zeroRoot(tree: Tree[Int]): Node[Int] = Node(0, tree, Empty())
f(Node(1, Empty(), Empty())(zeroRoot)
有效,因为我们传递的是zeroRoot
,它期望Node
(没关系),我们返回Tree
,其中转弯作为Node
返回(也可以)。
顺便说一下,Tree
可能应该是共变体。
现在,另一个反方差的例子是排序类。虽然Scala由于某些技术性而不变,但正确的排序应该是对立的。毕竟,如果您知道如何订购Tree
,那么您可以订购Tree
,因此Node
将是Ordering[Tree]
的子类型,因为第一个可以在第二个预期的地方通过。
我并没有真正密切关注代码,但有意义的是,用作排序的东西应该是反变量的。另一方面,似乎不可能使Ordering[Node]
逆变,因为Traversable
类型签名需要不变性。
通过将Functor
类型明确传递给Tree
来解决此问题,或明确将Sort
声明为tree2
。然后你会得到其他不同的问题! :)