【问题标题】:Assign an operator to a variable in Scala将运算符分配给Scala中的变量
【发布时间】:2014-10-01 14:40:39
【问题描述】:

鉴于 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] 的运算符 ++,因此:有没有办法将该运算符分配给变量?就像在这个虚构的例子中一样:

val mapMerge : (Map[VertexId, Factor], Map[VertexId, Factor]) => Map[VertexId, Factor] = Map.++

而且可能通过类型推断就足够了

val mapMerge = Map[VertexId,Factor].++

谢谢

【问题讨论】:

  • 你的问题是什么?

标签: scala operators


【解决方案1】:

很遗憾,不是,因为 Scala 中的“操作符”是 instance 方法,而不是像 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 创建了一个实现,我们在类型类中为方法使用类似运算符的名称。

因为您可以为任何类型实现类型类,所以您可以对任何类型使用这种技巧——但这需要编写相当多的支持代码,而且有时不值得这样做。

【讨论】:

    猜你喜欢
    • 2017-01-11
    • 2021-08-05
    • 2020-01-18
    • 1970-01-01
    • 1970-01-01
    • 2014-12-06
    • 2018-06-15
    • 2020-08-07
    相关资源
    最近更新 更多