The correct answer is in fact the following:
https://fsharpforfunandprofit.com/posts/elevated-world/#apply
If one needs some code then it boils down to about the following example:
module Option = // The apply function for Options let apply fOpt xOpt = match fOpt,xOpt with | Some f, Some x -> Some (f x) | _ -> None let (<!>) = Option.map let (<*>) = Option.apply let a = Some(4) let b = Some(5) let multiplication = (*) //Some multiplication function applied on a and resulting function applied on b let res1 = Some(multiplication) <*> a <*> b let res2 = Some(*) <*> a <*> b //Map a onto multiplication function and resulting function applied on b let res3 = multiplication <!> a <*> b let res4 = (*) <!> a <*> b val res1 : int option = Some 20 val res2 : int option = Some 20 val res3 : int option = Some 20 val res4 : int option = Some 20 //The following is without any options to try to clarify the above let op = (*) //multiplication //let partialRes = (*) 4 let partialRes = op 4 //make function for multiplying param with 4 let fullres = partialRes 5 //use function for multiplying with 4 val op : (int -> int -> int) val partialRes : (int -> int) val fullres : int = 20
The reason for saying this is that with the above one can work in and out of what Wlaschin calls "elevated world", or Option in this case, and mix stuff from both. Kind of. Read the full site or book Wlaschin has written for good measure.
There is no need to make any function taking an Option as a param and the wrapping and unwrapping can be taken care of once and for all.
As the above code shows (shamelessly stolen from link, and somewhat rewritten), the function Richard needs is:
Option.apply
Yes the symbols will possibly confuse especially since we are talking multiplication or * here, but these symbols for map <!> and apply <*> are somewhat 'standard'.
I think the comments in the code are more or less correct with regards to how to read the code.
And yes, I maybe need to work on my teaching styles ;-)