Optional parameters and option types using F#

  1. fn2 works because fn1 does not use its parameter, which is thus generic 'b option.

    type Test () =
       member o.fn1 (?bo1) = 1  --> bo1: 'b option, here 'b = 'a option
       member o.fn2 (?bo) = o.fn1 bo  -->bo: 'a option
    
  2. fn4 complains that the parameter passed to fn3 should be an int, but not int option because when you specify the parameter, you of course need to pass in a specific one. But you have the option to omit the parameter. The definition/type signature of fn3 does not know whether you have specify bo or not, so it is a int option. Notice that you may have the following usage:

    type Test () =
       member o.fn1 (?bo) = 1
       member o.fn2 (?bo) = o.fn1 bo
    
       member o.fn3 (?bo) = 
       match bo with
         | Some v -> 1 + bo.Value
         | None -> 1
    
       member o.fn4 (?bo) = o.fn3()
    

where you don't specify the parameter for fn3, but when you specify it, it is a concrete int, not int option.

Think about a plotting function with three parameters:

let plot(?x,?y,?color)

because the parameters are optional, you can have the following usage:

plot(data)
plot(y=data)
plot(x=data, color='r')

But not:

plot(Some data)
plot(y=Some data)
plot(x=Some data, color=Some 'r')

F# does not require matching to pass optional arguments. Using the plot-example:

type Plotter() =
    static member Plot(?x,?y,?color) = 
        printfn $"{x}, {y}, {color}" // Do something "plottish" here

type PlotUser() =
    static member MyPlotUser(?x, ?y, ?color) =
        Plotter.Plot(?x = x, ?y = y, ?color = color)

/// Perform calls
PlotUser.MyPlotUser(10) // => Some(10), , 
PlotUser.MyPlotUser(10, color = "Green") // => Some(10), , Some(Green)

The above lets you call plot with your own optional arguments. /JEE, Sharp#Soft


I have to reconsider the correct answer. Based on this question (and answer):

Propagating optional arguments

it seams that the correct answer is the following:

type Test () =
  member o.fn1 (?bo) = 1
  member o.fn2 (?bo) = o.fn1 bo

  member o.fn3 (?bo) = 1 + bo.Value
  member o.fn4 (?bo) = o.fn3 (?bo = bo)

It is a neat feature and credits for the answer go to desco!