【问题标题】:Creating infix operators in Scala在 Scala 中创建中缀运算符
【发布时间】:2014-07-16 10:19:54
【问题描述】:

我正在尝试将我的一些 Haskell 代码翻译成 Scala,但在创建中缀运算符时遇到了困难。

在 Haskell 中,我将这个中缀运算符定义为:

infix 1 <=>                          // this specifies the operator precedence
(<=>) :: Bool -> Bool -> Bool        // this is the type signature of this operator (it says, it takes two Boolean values and returns a Boolean value)
x <=> y = x == y                     // this is the definition of the operator, it is mimicking the behaviour of the logical implication 'if-and-only-if'

所以现在如果我有两个布尔值,p 和 q,其中 p == True 和 q == False,p q 将返回 False。

我的问题是如何将其翻译成 Scala。我查看了 Odersky 的 Programming in Scala 书中定义的 Rational 类, 试图效仿这个例子。这是据我所知:

class Iff (b : Boolean){
  def <=> (that : Boolean) : Boolean = {
    this.b == that
  }
}

val a = new Iff(true)
println(a.<=>(false))  // returns false as expected

我可能没有在惯用的 Scala 中做到这一点,所以我正在该部门寻求帮助。

我的问题是:

  1. 我是否在 Scala 中惯用地实现了这一点?如果不是,那么在 Scala 中最好的方法是什么?
  2. 我是否必须创建该类才能定义此运算符?意思是,我可以像上面的 Haskell 代码那样在 Scala 中定义一个独立的方法吗?
  3. 如何在Scala中指定算子的固定级别?也就是说,它是优先级。

【问题讨论】:

  • 有趣的是,Scala 中的运算符优先级is fixed

标签: scala haskell


【解决方案1】:

你可以定义implicit class

implicit class Iff(val b: Boolean) extends AnyVal {
  def <=>(that: Boolean) = this.b == that
}

现在你可以不用new来调用它了:

true <=> false // false
false <=> true // false
true <=> true  // true

【讨论】:

  • 有什么理由创建一个值类 (extends AnyVal) 吗?它也可以不使用。
  • 是的,没有它也可以工作,但是根据docs,通过使用AnyVal 扩展类,您可以避免在运行时分配对象,而是将其表示为它的基础值——在构造函数。因此,在这种情况下,在运行时,您的类 Iff 将表示为 Boolean
  • @ccheneson 由于您已将问题标记为 Haskell,这可能有助于您理解:在 Scala 中扩展 AnyVal 与在 Haskell 中使用 newtype 而不是 data 基本相同。它在编译时创建一个在运行时不存在的包装器。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-09-22
  • 2013-11-13
  • 2011-11-28
  • 2015-07-26
相关资源
最近更新 更多