gpt4 book ai didi

scala - 如何区分 def foo[A](xs : A*) and def foo[A, B](xs : (A, B)*)?

转载 作者:行者123 更新时间:2023-12-03 01:52:44 25 4
gpt4 key购买 nike

我知道类型删除使它们在运行时在类型上看起来相等,因此:

class Bar {
def foo[A](xs: A*) { xs.foreach(println) }
def foo[A, B](xs: (A, B)*) { xs.foreach(x => println(x._1 + " - " + x._2)) }
}

给出以下编译器错误:

<console>:7: error: double definition:
method foo:[A,B](xs: (A, B)*)Unit and
method foo:[A](xs: A*)Unit at line 6
have same type after erasure: (xs: Seq)Unit
def foo[A,B](xs: (A, B)*) { xs.foreach(x => println(x._1 + " - " + x._2)
) }
^

但是有没有一种简单的方法可以编写:

bar.foo(1, 2, 3)
bar.foo(1 -> 2, 3 -> 4)

并让它们调用 foo 的不同重载版本,而不必显式命名它们:

bar.fooInts(1, 2, 3)
bar.fooPairs(1 -> 2, 3 -> 4)

最佳答案

你可以,以一种相当迂回的方式。 Foo 是一个类型类,编译器隐式传递该类型类的实例,与(推断的)类型参数 A 兼容。

trait Foo[X] {
def apply(xs: Seq[X]): Unit
}

object Foo {
implicit def FooAny[A]: Foo[A] = new Foo[A] {
def apply(xs: Seq[A]) = println("apply(xs: Seq[A])")
}
implicit def FooTuple2[A, B]: Foo[(A, B)] = new Foo[(A, B)] {
def apply(xs: Seq[(A, B)]) = println("apply(xs: Seq[(A, B)])")
}

def apply[A](xs: A*)(implicit f: Foo[A]) = f(xs)
}


Foo(1, 2, 3) // apply(xs: Seq[A])
Foo(1 -> 2, 2 -> 3) // apply(xs: Seq[(A, B)])

在第二次调用中,FooAnyFooTuple2 都可以传递,但编译器根据静态方法的规则选择 FooTuple2重载。 FooTuple2 被认为比 FooAny 更具体。如果两个候选者被认为彼此一样具体,则会出现歧义错误。您还可以通过将其中一个放在父类(super class)中来优先选择其中一个,如 scala.LowPriorityImplicits 中所做的那样。

更新

借鉴 DummyImplicit 的想法,以及 scala-user 上的后续线程:

trait __[+_]
object __ {
implicit object __ extends __[Any]
}

object overload {
def foo(a: Seq[Boolean]) = 0

def foo[_: __](a: Seq[Int]) = 1

def foo[_: __ : __](a: Seq[String]) = 2
}

import overload._
foo(Seq(true))
foo(Seq(1))
foo(Seq("s"))

这声明了一个类型参数化特征__,在其未命名类型参数_中是协变的。它的伴生对象 __ 包含 __[Any] 的隐式实例,我们稍后会需要它。 foo 的第二个和第三个重载包含一个虚拟类型参数,同样是未命名的。这将被推断为 Any。该类型参数具有一个或多个上下文边界,这些边界被脱糖为额外的隐式参数,例如:

 def foo[A](a: Seq[Int])(implicit ev$1: __[A]) = 1

多个参数列表在字节码中连接成单个参数列表,因此避免了双重定义问题。

请将此视为了解删除、上下文边界和隐式搜索的机会,而不是作为在实际代码中应用的模式!

关于scala - 如何区分 def foo[A](xs : A*) and def foo[A, B](xs : (A, B)*)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3422336/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com