# Convert a binary function of Double to binary function of Option[Double]

I have a curry-able function for comparing Doubles

``````  def almostEqual(tolerance:Double)(x:Double, y:Double):Boolean = {
( x == y) ||  abs(x - y ) < tolerance * max(abs(x),abs(y))
}
``````

I often call the function like `almostEqual(0.01)` to return me a binary function for testing whether two given Doubles are within 1 percent of each other.

In several cases I have Option[Double] rather than Double. So I wrote the following function, so I can use `ae(0.01)` to give me a function of type `(Option[Double],Option[Double])=>Boolean` which will be a function to determine whether the two underlying numbers are within 1 percent of each other.

My gut feel is that there is a much easier way to do this. What is the best way to write the function which takes `almostEqual` as argument and returns something isomorphic to `ae` ?

``````    def optionAlmostEqual(test:(Double,Double)=>Boolean):(Option[Double],Option[Double])=>Boolean = {
(op1,op2) => {
(op1,op2) match {
case (Some(a),Some(b)) => test(a,b)
case _ => false
}
}
}
def ae(delta:Double):(Option[Double],Option[Double])=>Boolean = {
optionAlmostEqual(almostEqual(delta))
}
``````

Is the following better?

``````def testOp(test: (Double, Double) => Boolean)(
fst: Option[Double], snd : Option[Double]
) = {
for {
x<- fst
y <- snd
} yield test(x, y)}.getOrElse(false)
``````

best
Siddhartha

I was wondering whether it could be done with something like `almostEqual.flatMap.tupled.getOrElse(false)` But that’s just an intuition.

You can shorten the code using scalaz library and its wealth of weird looking operators (I don’t recommend it, though).

``````  // original solution
def optionAlmostEqual1(test: (Double, Double) => Boolean)
: (Option[Double], Option[Double]) => Boolean = (op1, op2) => {
(op1, op2) match {
case (Some(a), Some(b)) => test(a, b)
case _                  => false
}
}

def optionAlmostEqual2(test: (Double, Double) => Boolean)
: (Option[Double], Option[Double]) => Boolean = (o1, o2) => {
(for (d1 <- o1; d2 <- o2) yield test(d1, d2)).getOrElse(false)
}

// solution using scalaz library
def optionAlmostEqual3(test: (Double, Double) => Boolean)
: (Option[Double], Option[Double]) => Boolean = (o1, o2) => {
import scalaz._
import Scalaz.{test => _, _}
(o1 |@| o2)(test) | false
}
``````
1 Like

Don’t use the Applicative builder. Just use Apply

import scalaz.Apply
Apply[Option].apply2(maybeDouble1, maybeDouble2)(test).getOrElse(false)

The Cats library also has an Apply with slightly different naming.

1 Like