yiksanchan
yiksanchan

Reputation: 1940

How to define a scala method with type param that cannot be Any

In below example, I want to define a contains method that doesn't compile if a and b are not of the same base type.

def contains1[T](a: Seq[T], b: T): Boolean = a.contains(b)

println(contains1(Seq(1,2,3), "four")) // false

def contains2[T: Ordering](a: Seq[T], b: T): Boolean = a.contains(b)

println(contains2(Seq(1,2,3), "four")) // compilation error
// cmd7.sc:1: No implicit Ordering defined for Any.
// val res7 = isMatched(Seq(1,2,3), "s")
                    ^
// Compilation Failed

However, is there a simpler way to achieve the same behaviour as in contains2? Ordering context bound confuses me as the method has nothing to do with sorting/ordering at all.

Upvotes: 9

Views: 190

Answers (1)

Krzysztof Atłasik
Krzysztof Atłasik

Reputation: 22635

You could use generalized type constraints operator =:=.

For example:

def contains[A,B](a: Seq[A], b: B)(implicit evidence: A =:= B): Boolean = a.contains(b)

and then:

println(contains1(Seq(1,2,3), "four")) //fails with Cannot prove that Int =:= String.
println(contains1(Seq("one"), "four")) //returns false
println(contains1(Seq("one", "four"), "four")) //true

More on generalized type constraints here and here.

As LuisMiguelMejíaSuárez noticed, you could also consider using B <:< A instead of A =:= B. I won't elaborate on differences between these two because it's described in linked answer and article, but in brief, <:< would also allow all B that are a subtype of A, while =:= needs types to match exactly.

Upvotes: 9

Related Questions