鉴于Scala中有这么多代码:
val mapMerge : (Map[VertexId, Factor], Map[VertexId, Factor]) => Map[VertexId, Factor] = (d1, d2) => d1 ++ d2
可以缩短为:
val mapMerge : (Map[VertexId, Factor], Map[VertexId, Factor]) => Map[VertexId, Factor] = _ ++ _
实际上代码的作用是重命名Map [VertexId,Factor]的operator ++,因此:有没有办法将该运算符赋值给变量?就像在这个想象中的例子一样:
val mapMerge : (Map[VertexId, Factor], Map[VertexId, Factor]) => Map[VertexId, Factor] = Map.++
并且可能使用类型推断就可以编写
了val mapMerge = Map[VertexId,Factor].++
由于
答案 0 :(得分:6)
不幸的是,不,因为"运营商" Scala中的实例方法 - 不是来自类型类的函数,就像在Haskell中一样
在你编写_ ++ _
时,你正在创建一个带有未命名参数的新的2参数函数(lambda)。这相当于(a, b) => a ++ b
,相当于(a, b) => a.++(b)
,但不等同于(a, b) => SomeClass.++(a, b)
。
您可以使用隐式参数来模拟类型类(请参阅"typeclasses in scala" presentation)
你可以通过"运营商"像函数 - 它们不是真正的运算符。你可以拥有看起来相同的运营商。见this example:
object Main {
trait Concat[A] { def ++ (x: A, y: A): A }
implicit object IntConcat extends Concat[Int] {
override def ++ (x: Int, y: Int): Int = (x.toString + y.toString).toInt
}
implicit class ConcatOperators[A: Concat](x: A) {
def ++ (y: A) = implicitly[Concat[A]].++(x, y)
}
def main(args: Array[String]): Unit = {
val a = 1234
val b = 765
val c = a ++ b // Instance method from ConcatOperators — can be used with infix notation like other built-in "operators"
println(c)
val d = highOrderTest(a, b)(IntConcat.++) // 2-argument method from the typeclass instance
println(d)
// both calls to println print "1234765"
}
def highOrderTest[A](x: A, y: A)(fun: (A, A) => A) = fun(x, y)
}
这里我们定义Concat类型类并为Int创建一个实现,我们在类型类中使用类似运算符的名称。
因为你可以为任何类型实现一个类型类,你可以使用任何类型的这种技巧 - 但这需要编写相当多的支持代码,有时它不值得结果。