Home > Back-end >  Can an F# generic type constraint specify more than 1 valid type?
Can an F# generic type constraint specify more than 1 valid type?

Time:12-31

I have this sample function signature:

let func1 (input:'a when 'a :> (IReadOnlyDictionary<string, string>)) =
...

I would also like to permit 'a to be an IDictionary<string, string>). So either type could be passed. The code that uses the input parameter calls TryGetValue which both interfaces support.

Is it possible to specify an OR type constraint like this? If so, what is the specific syntax to do so?

CodePudding user response:

I'm pretty sure you can't, but you can use SRTP to require the TryGetValue method:

let inline func1 (input : 'a when 'a : (member TryGetValue : string * byref<string> -> bool)) =
    let mutable value = ""
    let flag = input.TryGetValue("key", &value)
    flag, value

It's ugly, but it works. Here it's called with an IDictionary:

dict [ "key", "value" ]
    |> func1
    |> printfn "%A"   // (true, "value")

And here it's called in an IReadOnlyDictionary:

dict [ "key", "value" ]
    |> System.Collections.ObjectModel.ReadOnlyDictionary
    :> System.Collections.Generic.IReadOnlyDictionary<_, _>
    |> func1
    |> printfn "%A"   // (true, "value")
  • Related