Performing Calculations on F # Option Types

I am trying to write some function that handles errors by returning double options instead of double local ones. Many of these functions call each other and therefore take double parameters as input to output other double options. The problem is that I cannot do with double options, what I can do with doubles - something as simple as adding them with "+".

For example, a function that divides two doubles and returns a double option for which there is no division by zero error. Then another function calls the first function and adds another double option to it.

Please tell me if there is a way to do this, or if I completely misunderstood the meaning of F # option types.

+3


source to share


4 answers


This is called hoisting - you can write a function to hoist another function in two ways:

let liftOpt f o1 o2 = 
        match (o1, o2) with
        | (Some(v1), Some(v2)) -> Some(f v1 v2)
        | _ -> None

      



then you can provide a function to apply, for example:

let inline addOpt o1 o2 = liftOpt (+) o1 o2

      

+9


source


liftA2

, as mentioned above, will provide a general way to "hoist" any function that accepts arguments double

to a function that can operate on arguments double option

.

However, in your case, you might have to write special functions yourself to handle the edge cases you mention

let (<+>) a b =
    match (a, b) with
    | (Some x, Some y) -> Some (x + y)
    | (Some x, None)   -> Some (x)
    | (None, Some x)   -> Some (x)
    | (None, None)     -> None

      

Please note that liftA2

it will not put cases where you want to automatically add None

to Some(x)

.

The method liftA2

for splitting also needs special handling, but its structure is usually that we will write

let (</>) a b =
    match (a, b) with
    | (Some x, Some y) when y <> 0.0d -> Some (x/y)
    | _ -> None

      



You can use these functions like

Some(2.0) <+> Some(3.0) // will give Some(5.0)
Some(1.0) </> Some(0.0) // will give None

      

Also, strictly speaking, lift

defined as a "higher order function" - something that takes a function and returns another function.

So it looks something like this:

let liftOpt2 f =
    (function a b ->
        match (a, b) with
        | (Some (a), Some (b)) -> f a b |> Some
        | _ -> None)

      

+2


source


Eventually, I realized that I was really looking for the Option.get function, which just takes an "option" and returns "a". This way I can match the image and return the values ​​I want.

0


source


In this case, you may need to enable Nullables in Options, for two reasons:

  • Nullables are value types and options are reference types. If you have large collections of these doubles, using Nullables will keep the numbers on the stack instead of piling them up, potentially improving your performance.
  • Microsoft provides a bunch of built-in Nullable Operators that allow you to directly do math on nullables values, just like you're trying to do with options.
0


source







All Articles