I'm trying to achieve something with ScalaTest and based on C. Hosrtmann's "Scala for the impatient" I think this is related to "Family polymorphism". Apparently I don't understand something about Scala's type system, so I fail.
To cut the long story short, this is what I'm trying to do.
I have a base (production) trait:
trait MaxPQ[Key] {
implicit protected val cmp: Ordering[_ >: Key]
...
def insert(v: Key): Unit
def max(): Key
def delMax(): Key
...
}
then there is a number of implementations (that use either a backing tree or an array).
In tests I want to create an abstract structure which would allow to test any implementation for three Ordered
Key
s: Char
, Int
, Double
.
First I've written two behaviors (for empty and non-empty priority queues). Here's a snippet:
trait MaxPQBehaviours {
// underlying tests spec
self: BaseSpec =>
def nonEmptyMaxPQ[T <: Ordered[T], ImplLà <: MaxPQ[T]](instanceSupplier: () => ImplLà, sortedInput: List[T]): Unit = {
...
behavior of "size"
it should s"be equal to ${sortedInput.size}" in {
val instance = instanceSupplier()
instance.size() shouldEqual sortedInput.size
}
behavior of "max"
it should s"return the expected $max" in {
val instance = instanceSupplier()
instance.max() shouldEqual max
}
...
Finally to add a last layer of abstraction I'm adding a BaseMaxPQSpec
that mixes-in the above MaxPQBehaviours
and calls its behaviors for three abstract MaxPQ
types. Here I'only provide example for Char
:
trait BaseMaxPQSpec extends BaseSpec with MaxPQBehaviours {
type CharMaXPQ <: MaxPQ[Char]
def charMaxPQ: CharMaXPQ
val sortedCharsList: List[Char] = List[Char]('C', 'b', 'd', 'a', 'z').sorted
it should behave like nonEmptyMaxPQ(() => charMaxPQ, sortedCharsList)
}
And this is where compiler spits this at me:
[error] ~/Algorithms/Chapter 2 Sorting/algorithms2_1/src/test/scala/ca/vgorcinschi/algorithms2_4/BaseMaxPQSpec.scala:18:25: inferred type arguments [Char,BaseMaxPQSpec.this.CharMaXPQ] do not conform to method nonEmptyMaxPQ's type parameter bounds [T <: Ordered[T],ImplLà <: ca.vgorcinschi.algorithms2_4.MaxPQ[T]]
[error] it should behave like nonEmptyMaxPQ(() => charMaxPQ, sortedCharsList)
[error] ^
[error] ~/Algorithms/Chapter 2 Sorting/algorithms2_1/src/test/scala/ca/vgorcinschi/algorithms2_4/BaseMaxPQSpec.scala:18:42: type mismatch;
[error] found : () => BaseMaxPQSpec.this.CharMaXPQ
[error] required: () => ImplLà
[error] it should behave like nonEmptyMaxPQ(() => charMaxPQ, sortedCharsList)
[error] ^
[error] ~/Algorithms/Chapter 2 Sorting/algorithms2_1/src/test/scala/ca/vgorcinschi/algorithms2_4/BaseMaxPQSpec.scala:18:56: type mismatch;
[error] found : List[Char]
[error] required: List[T]
[error] it should behave like nonEmptyMaxPQ(() => charMaxPQ, sortedCharsList)
[error] ^
[error] three errors found
[error] (Test / compileIncremental) Compilation failed
[error] Total time: 12 s, completed Feb 15, 2020 6:21:35 PM
What is the correct way to set-up my testing framework? Please don't hesitate to ask for details, clarifications.