【问题标题】:Overcoming type erasure in Scala in cases of different return types在不同返回类型的情况下克服 Scala 中的类型擦除
【发布时间】:2016-08-03 18:27:36
【问题描述】:

我要定义以下两个Scala函数:

def Pr(
  f: Int => Int,
  g: Tuple3[Int, Int, Int] => Int
): Tuple2[Int, Int] => Int = {
  def recurse(x: Int, counter: Int): Int = counter match {
    case 0 => f(x)
    case y => g(x, y-1, recurse(x, y-1))
  }
  (recurse _).tupled
}

def Pr(
  f: Tuple2[Int, Int] => Int,
  g: Tuple4[Int, Int, Int, Int] => Int
): Tuple3[Int, Int, Int] => Int = {
  def recurse(x1: Int, x2: Int, counter: Int): Int = counter match {
    case 0 => f(x1, x2)
    case y => g(x1, x2, y-1, recurse(x1, x2, y-1))
  }
  (recurse _).tupled
}

这里的基本思想是,如果f 是n-ary,g 是(n+2)-ary,那么Pr(f,g) 是(n+1)-ary。当然,问题是类型擦除。类型擦除后fg 都是Function1 的,这两个Pr 函数是无法区分的。我认为创建一个带有类型标签的 Pr 函数在这里可能会有所帮助,但我不确定如何在每种情况下更改返回类型。

接受任何建议;可以在不使用其他库(Shapeless、Scalaz)的情况下解决这个问题的优先。

【问题讨论】:

  • 可以在此处使用磁铁图案,但不要。只是给他们不同的名字。
  • (旁注:95% 的时间类型擦除是你的朋友。如果它使某些事情变得不可能,那可能是一件坏事。)

标签: scala generics type-erasure


【解决方案1】:

对于另外 5%,标准习语(早于磁化)是添加一个虚拟的隐式参数列表:

def Pr(
  f: Tuple2[Int, Int] => Int,
  g: Tuple4[Int, Int, Int, Int] => Int
)(implicit dummy: DummyImplicit): Tuple3[Int, Int, Int] => Int = {
  def recurse(x1: Int, x2: Int, counter: Int): Int = counter match {
    case 0 => f(x1, x2)
    case y => g(x1, x2, y-1, recurse(x1, x2, y-1))
  }
  (recurse _).tupled
}

肯定有无数的问答。

Scala 重载只考虑第一个参数列表;虚拟参数是消除已擦除签名的歧义。

模重载是邪恶的,Travis Brown 的博客是关于在 Scala 中做一些你可能不应该做的不可能的事情,他说这可能不是一件好事。全面披露,tl;博士。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-04-10
    • 2019-06-30
    • 1970-01-01
    • 1970-01-01
    • 2020-04-17
    • 1970-01-01
    • 2012-09-19
    • 2012-05-28
    相关资源
    最近更新 更多