Reputation: 13
I'm trying to implement a set based on a weight-based tree in Scala. I have the following class hierarchy:
case class Node[K, V](key: K, value: Option[V] = None, left: Option[Node[K, V]] = None, right: Option[Node[K, V]] = None, size: Int = 1)(implicit ord: K => Ordered[K])
case class Tree[K, V](root: Option[Node[K, V]] = None, alpha: Double = 0.25)(implicit ord: K => Ordered[K])
case class WBTreeSet[K](tree: Tree[K, Nothing] = Tree[K, Nothing]())(implicit ord: K => Ordered[K])
Classes get Ordered[K]
implicitly so that I can compare elements of type K and build the tree.
When I try to compile the code, I get the following errors:
No implicit view available from K => Ordered[K].
Error occurred in an application involving default arguments.
case class WBTreeSet[K](tree: Tree[K, Nothing] = Tree[K, Nothing]())(implicit ord: K => Ordered[K]) {
not enough arguments for method apply: (implicit ord: K => Ordered[K])Tree[K,Nothing] in object Tree.
Unspecified value parameter ord.
Error occurred in an application involving default arguments.
case class WBTreeSet[K](tree: Tree[K, Nothing] = Tree[K, Nothing]())(implicit ord: K => Ordered[K]) {
When I delete the default value for tree
in WBTreeSet
, the code compiles.
I'm using Scala for the first time and I have already searched a lot of similar problems, however I still cannot resolve this issue. Is there any way to fix this without changing the structure of classes or should I do it another way?
Upvotes: 1
Views: 499
Reputation: 10764
I suppose you expect the implicit ord
parameter of WBTreeSet
to be passed to default value of tree
parameter. Unfortunately, this will not work because in Scala, default parameter values cannot refer to other parameter values in the same parameter list or in subsequent parameter lists, e.g.
def thisWillWork(a: Int)(b: Int = a*2) = ???
def thisWillNotWork(a: Int, b: Int = a*2) = ???
def thisWillNotWork(a: Int = b*2)(b: Int) = ???
That, plus the fact that implicit parameters can only be passed in the last parameter list means that your tree
param default value cannot access ord
param.
How to work around this?
First, prefer using Ordering
typeclass instead of implicit conversion to Ordered
, e.g.
case class Node[K, V](...)(implicit ord: Ordering[K])
or shorter, using context bound syntax:
case class Node[K: Ordering, V](...)
Then, if you want to keep your default value, you probably have to use overloaded apply
method instead of default parameter value:
case class WBTreeSet[K: Ordering](tree: Tree[K, Nothing])
object WBTreeSet {
def apply[K: Ordering](): WBTreeSet[K] = WBTreeSet[K](Tree[K,Nothing]())
}
Upvotes: 1
Reputation: 51658
Try overloaded apply
methods:
case class Node[K, V](key: K, value: Option[V] = None, left: Option[Node[K, V]] = None, right: Option[Node[K, V]] = None, size: Int = 1)(implicit ord: K => Ordered[K])
case class Tree[K, V](root: Option[Node[K, V]] = None, alpha: Double = 0.25)(implicit ord: K => Ordered[K])
case class WBTreeSet[K](tree: Tree[K, Nothing])(implicit ord: K => Ordered[K])
object WBTreeSet {
def apply[K](implicit ord: K => Ordered[K]): WBTreeSet[K] = WBTreeSet(Tree[K, Nothing]())
}
Upvotes: 0