【发布时间】:2021-11-04 14:16:33
【问题描述】:
由于 Scala 2.12(或者是 2.13,不能确定),编译器可以跨多个方法推断潜在类型参数:
def commutative[
A,
B
]: ((A, B) => (B, A)) = {???} // implementing omitted
val a = (1 -> "a")
val b = commutative.apply(a)
最后一行成功推断出A = Int, B = String,不幸的是,这需要给出一个实例a: (Int, String)。
现在我想稍微扭曲一下这个 API 并定义以下函数:
def findApplicable[T](fn: Any => Any)
这样findApplicable[(Int, String)](commutative) 会自动生成为A = Int, B = String 专用的正确函数。有没有办法在语言的能力范围内做到这一点?或者我必须升级到 scala 3 才能做到这一点?
UPDATE 1 需要注意的是,commutative 的输出可以是任何类型,不一定是 Function2,例如我尝试了以下定义:
trait SummonedFn[-I, +O] extends (I => O) {
final def summon[II <: I]: this.type = this
}
然后重新定义commutative来使用它:
def commutative[
A,
B
]: SummonedFn[(A, B), (B, A)] = {???} // implementing omitted
val b = commutative.summon[(Int, String)]
糟糕,这不起作用,类型参数不像值参数那样得到同等对待
【问题讨论】:
-
不确定你为什么想要/需要
findApplicable,你能详细说明一下吗? -
它用于类似于 LEANprover 的“策略模式”(typista.org/lean-for-scala-programmers-4)的半自动类型验证。 “commutative”函数是 (A, B) 的建设性证明的一个示例(有关此类比的详细信息,请参见 Curry-Howard 同构:en.wikipedia.org/wiki/Curry%E2%80%93Howard_correspondence)。在战术模式下,用户只给出证明的名称和输入,编译器应该确定其余的
-
"commutative" 是玩具示例的一部分,生产用途将用于证明复杂张量代数管道和神经架构的稳健性:github.com/tribbloid/shapesafe
-
请注意,除非您将
commutative的返回类型替换为((A, B)) => (B, A),否则您的第一个示例不会编译。如果您还想对函数的数量进行抽象,那么您还有另一个问题。
标签: scala scala-2.13 polymorphic-functions