# 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
{"ft_lang_label":"__label__en","ft_lang_prob":0.78050166,"math_prob":0.973473,"size":1100,"snap":"2022-40-2023-06","text_gpt3_token_len":274,"char_repetition_ratio":0.17518248,"word_repetition_ratio":0.03797468,"special_character_ratio":0.26818183,"punctuation_ratio":0.123809524,"nsfw_num_words":0,"has_unicode_error":false,"math_prob_llama3":0.9978522,"pos_list":[0],"im_url_duplicate_count":[null],"WARC_HEADER":"{\"WARC-Type\":\"response\",\"WARC-Date\":\"2023-01-30T05:02:08Z\",\"WARC-Record-ID\":\"<urn:uuid:161a5841-2647-47ea-85a4-9dce1610434c>\",\"Content-Length\":\"23580\",\"Content-Type\":\"application/http; msgtype=response\",\"WARC-Warcinfo-ID\":\"<urn:uuid:1023a2ed-31f2-4d16-9ec8-b5546b540ae2>\",\"WARC-Concurrent-To\":\"<urn:uuid:93cdadf5-5b1e-4d43-bed5-9cffa83c9432>\",\"WARC-IP-Address\":\"128.178.218.46\",\"WARC-Target-URI\":\"https://users.scala-lang.org/t/convert-a-binary-function-of-double-to-binary-function-of-option-double/4358\",\"WARC-Payload-Digest\":\"sha1:VDCL5QCYFJDXCHQ6SSZQ5I6XNPCGN4KF\",\"WARC-Block-Digest\":\"sha1:MI6ZO6WOGRH5ABS7CYITA6VW3C6XOJAN\",\"WARC-Identified-Payload-Type\":\"text/html\",\"warc_filename\":\"/cc_download/warc_2023/CC-MAIN-2023-06/CC-MAIN-2023-06_segments_1674764499801.40_warc_CC-MAIN-20230130034805-20230130064805-00401.warc.gz\"}"}