无优先级队列标量中的类型

时间:2017-08-02 10:02:42

标签: scala functional-programming

我使用优先级队列来命令一个名为TreeNodeWithCostAndHeuristic的案例类

  case class TreeNodeWithCostAndHeuristic[S,A](parent:Option[TreeNodeWithCostAndHeuristic[S,A]],
                                           action: Option[A],
                                           state: S,
                                           cost: Double,
                                           estimatedRemainingCost: Double)

此优先级队列在函数内创建,该函数使用其参数设置初始状态,而其他值必须保持为None或0

  def HeuristicGraphSearch[S,A](problem: ProblemWithCostAndHeuristic[S,A]) = {
    val root = TreeNodeWithCostAndHeuristic(parent = None,action=None,state=problem.initialState,cost = 0.0, estimatedRemainingCost = 0.0)
    val frontier : mutable.PriorityQueue[TreeNodeWithCostAndHeuristic[S,A]] = mutable.PriorityQueue.empty[TreeNodeWithCostAndHeuristic[S,A]]
    frontier.enqueue(root)

然而,由于父母和行动都不是,我在预期类型TreeNodeWithCostAndHeuristic[S,A]和我试图入队TreeNodeWithCostAndHeuristic[S,Nothing]之间的不匹配。

据我所知,Nothing是Option的子类型,在我的case类中,parent和action都是选项。为什么我会遇到不匹配?

2 个答案:

答案 0 :(得分:2)

它与Scala编译器推断类型的方式有关。简短的回答是通过在构造案例类时明确声明类型来简单地帮助它:

val root = TreeNodeWithCostAndHeuristic[S, A](parent = None,action=None,state=problem.initialState,cost = 0.0, estimatedRemainingCost = 0.0)

TreeNodeWithCostAndHeuristic[S, Nothing]不被视为TreeNodeWithCostAndHeuristic[S, A]的有效替代的原因是因为它不是它的子类;要成为一个,它必须在类型A中是协变的。如果某个Foo[A]在其类型A中是协变的,则只有以下内容成立:Foo[S] <: Foo[A]适用于任何S这是A的子类。

答案 1 :(得分:1)

除了sloucs回答,您还可以使用type ascription来帮助编译器:

val root = TreeNodeWithCostAndHeuristic(
    parent = None: Option[TreeNodeWithCostAndHeuristic[S, A]],
    action = None: Option[A],
    state = problem.initialState,
    cost = 0.0,
    estimatedRemainingCost = 0.0)

编译器抱怨的原因是它无法保证None.type 分别是 Option[TreeNodeWithCostAndHeuristic[S, A]]Option[A],因此它“保释out“和推断Nothing,这是所有类型的底部类型。

@Dima还建议使用Option.empty[A]

val root = TreeNodeWithCostAndHeuristic(
    parent = Option.empty,
    action = Option.empty[A],
    state = problem.initialState,
    cost = 0.0,
    estimatedRemainingCost = 0.0)