在Scala中创建中缀运算符

M.K*_*.K. 15 haskell scala

我正在尝试将我的一些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'
Run Code Online (Sandbox Code Playgroud)

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

我的问题是如何将其转换为Scala.我看了一下在Odersky的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
Run Code Online (Sandbox Code Playgroud)

我可能没有在惯用的Scala中这样做,所以我在那个部门寻求帮助.

我的问题是:

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

gor*_*ral 17

你可以定义 implicit class

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

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

true <=> false // false
false <=> true // false
true <=> true  // true
Run Code Online (Sandbox Code Playgroud)

  • 是的,没有它可行但是根据[docs](http://docs.scala-lang.org/overviews/core/value-classes.html)通过使用`AnyVal`扩展类,你避免在运行时分配对象,相反,它表示为其基础值 - 在构造函数中指定的值.所以在这种情况下,在运行时,你的类`Iff`将表示为`Boolean`. (5认同)
  • @ccheneson既然你已经将问题标记为Haskell,这可能有助于你的理解:在Scala中扩展`AnyVal`基本上与在Haskell中使用`newtype`而不是`data`相同.它在编译时创建一个在运行时不存在的包装器. (5认同)