如何使用不能为Any的参数类型定义Scala方法

时间:2019-06-17 18:32:59

标签: scala types type-constraints

在下面的示例中,我想定义一个containsa不是相同基本类型时不编译的b方法。

  • contains1中,如果aSeq[Int]并且b为String,则T派生为Any,并进行编译。这不是我想要的。
  • contains2暗示中,如果aSeq[Int]并且b是String,则它不会编译。行为就是我想要的。
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

但是,有没有更简单的方法来实现与contains2中相同的行为? Ordering上下文绑定使我感到困惑,因为该方法与排序/排序完全无关。

1 个答案:

答案 0 :(得分:9)

您可以使用一般类型约束运算符=:=

例如:

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

然后:

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

有关广义类型约束herehere的更多信息。

正如LuisMiguelMejíaSuárez所注意到的,您也可以考虑使用B <:< A代替A =:= B。我不会详细说明这两者之间的区别,因为在链接的答案和文章中对此进行了描述,但总而言之,<:<还将允许所有B的子类型A,而{ {1}}需要完全匹配的类型。