How do I type let's say a function that takes a record that has a field a
and any other field?
Is some equivalent of this Standard ML function possible in F#?
fun f {a: string, ...} = "Hello" ^ a;
Tried the following but these don't seem to be syntactically valid:
let f (r: {|a: string; _|}) = impl;
let g (r: {|a: string; ...|}) = impl;
You can achieve this kind of constraint with Statically Resolved Type Parameters like so:
let inline f< ^T when ^T: (member a: string)> (r: ^T) = ()
f {| a = "yeet" |} // compiles
f {| a = "yeet"; b = "yote" |} // compiles
f {| b = "yote" |} // error
Note that this isn't just for anonymous records. It will hold true for any type that has a member with the specified signature.
I also like to hide these things behind a module and extract the nasty SRTP stuff into an active pattern like so:
module M =
let inline private (|HasName|) x = (^a : (member Name: string) x)
let inline printName (HasName name) = printfn $"{name}"
type Person1 = { Name: string; Age: int }
type Person2 = { Name: string; Age: int; IsFunny: bool }
type Name(name) =
member _.Name = name
let p1 = { Name = "Phillip"; Age = 30 }
let p2 = { Name = "Phillip"; Age = 30; IsFunny = false }
let nm = Name "Phillip"
M.printName p1
M.printName p2
M.printName nm
This has the benefit of hiding the details of how you get the constraint "lined up correctly" and lets you easily re-use the signature in other things you want to publicly expose.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With