15

I am trying to translate some of my Haskell code into Scala and I am having difficulty with creating infix operators.

In Haskell say I have this infix operator defined as:

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'

So now if I have two booleans, p and q where p == True and q == False, p <=> q will return False.

My question is how do I go about translating this into Scala. I had a look at the Rational class defined in Odersky's Programming in Scala book and tried to follow the example. This is as far as I got:

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

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

I've probably not done this in idiomatic Scala so I am looking for help in that department.

My questions are:

  1. Have I implemented this idiomatically in Scala? If not, what is that best way to this in Scala?
  2. Did I have to create that class in order to define this operator? Meaning, can I define a standalone method in Scala like I have in the Haskell code above?
  3. How to specify the fixity level of the operator in Scala? That is, it's precedence level.
  • Interestingly, operator precedence in Scala [is fixed](http://stackoverflow.com/questions/2922347/operator-precedence-in-scala). – J. Abrahamson May 27 '14 at 13:23

1 Answers1

17

You can define implicit class

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

and now you can call it without using new :

true <=> false // false
false <=> true // false
true <=> true  // true
goral
  • 1,275
  • 11
  • 17
  • 1
    Any reason to create a Value class (`extends AnyVal`) ? It also works without. – ccheneson May 27 '14 at 14:52
  • 5
    Yes it works without it but according to [docs](http://docs.scala-lang.org/overviews/core/value-classes.html) by extending class with `AnyVal` you are avoiding allocating the object at runtime, instead it is represented as its underlying value - the one that is specified in the constructor. So in this case, at runtime, your class `Iff` will be represented as `Boolean`. – goral May 27 '14 at 15:06
  • 5
    @ccheneson Since you've tagged the question as Haskell, this might help your understanding: Extending `AnyVal` in Scala is basically the same as using `newtype` instead of `data` in Haskell. It creates a wrapper at compile time that doesn't exist at runtime. – Tobias Brandt May 27 '14 at 20:44