Conversion with arbitrary number of generic arguments

Hi all!

I am struggling with something that I feel should somehow be possible, but I don’t find a way how.

I boil it down to its essence:

Lets say I have a number of different functions, like

func1: string -> string -> int
func2: int -> int
func3: string -> string -> string

And now I have all of the input values, which correspond to the input arguments of those functions, but are wrapped in some kind of other type:

Option<string>

I have a general mechanism for how to unwrap the option and I want to have a convert function which I can call like this:

convert func1 : Option<string> -> Option<string -> int
convert func2 : Option<int> -> int
convert func3: Option<string> -> Option<string> -> string

Kind of lift a whole function up, without having a function for every argument count.

I hope I explaned this well. Please feel free to ask more.

Thank you guys

I’m not entirely sure what you are trying to do, and I have no idea if that is possible with an arbitrary number of arguments, but does this help at all?:

// Single value.

let func2 (value : int) = value * 2  

let func2Lifted = func2 |> Option.map 

let output2 = func2Lifted (Some 5) |> Option.defaultValue 0 

// Two values.

let func1 (str1 : string) (str2 : string) : string = (str1.Length + str2.Length) |> sprintf "%A" 

let func1Lifted = func1 |> Option.map2 // Note the extra “2” at the end here.

let output1 = func1Lifted (Some "Hello") (Some "Everyone") |> Option.defaultValue "Default" 

// val func2: value: int -> int
// val func2Lifted: (int option -> int option)
// val output2: int = 10
// val func1: str1: string -> str2: string -> string
// val func1Lifted: (string option -> string option -> string option)        
// val output1: string = "13"

An Option.map3 also exists and I don’t think it would be too difficult to make your own map4, map5, etc. as necessary.

1 Like

You might be interested in this technique:

If you import & open FSharpPlus (or write your own Option.apply with a <*> operator for it), you can do

let s : Option<string> = ...
let i : Option<int> = ...
Some func1 <*> s <*> s : Option<int>
Some func2 <*> i : Option<int>
Some func3 <*> s <*> s : Option<string>

and that can be expanded out to any arbitrary number of arguments.

1 Like