Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

F# integer comparison

Tags:

f#

Given a list int from -273 to 5526, I want to print the closest integer to zero. In case of you have equality (n and -n) we should take n.

let temps = // this contains => 1 -2 -8 4 5

let (|Greater|_|) a b = if a > b then Some() else None
let (|Smaller|_|) a b = if a < b then Some() else None

let compareTemperatures a b = 
   let distanceA = abs a 
   let distanceB = abs b
   match distanceA with
   | Greater distanceB -> b
   | Smaller distanceB -> a
   | _ -> abs a

printfn "%i" (temps |> Seq.reduce compareTemperatures)

And that returns -8 instead of 1. It seems correct to me and I can't find the bug but I'm new to F# so I might have make a mistake anywhere and can't see it :(

Thanks in advance

like image 405
Cedric Royer-Bertrand Avatar asked Aug 12 '26 05:08

Cedric Royer-Bertrand


1 Answers

I think you got the comparison the wrong way round - when you write:

match distanceA with
| Greater distanceB -> b
| Smaller distanceB -> a

Then distanceA gets passed as the second parameter to Greater and so you are returning b (in the first case) in case when b is further away from zero. The following will make it work:

match distanceA with
| Greater distanceB -> a
| Smaller distanceB -> b

That said, using active patterns for this just makes the code unnecessarily complicated (and makes it easy to introduce bugs like this one). The following does the same thing and it is easy to understand and also a lot simpler:

let compareTemperatures a b = 
  if abs a > abs b then b else a

temps |> Seq.reduce compareTemperatures

I think the lesson here is that pattern matching works really well for things like algebraic data types and option values, but it is not that useful for simple numerical comparisons where if works fine!

like image 153
Tomas Petricek Avatar answered Aug 14 '26 23:08

Tomas Petricek



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!