Optional parameters and option types using F#
fn2
works becausefn1
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
fn4
complains that the parameter passed tofn3
should be an int, but notint 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 offn3
does not know whether you have specifybo
or not, so it is aint 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!