In an f# project I have the following types:
type A = { Name: string }
type B = { Name: string; SurName: string }
type C = { Name: string; SurName: string; MaidenName: string }
and the following function using a constraint on the generic argument:
let inline filterByName<'a when 'a: (member Name: string)> (name: string) (collection: 'a seq) =
collection |> Seq.where(fun i -> i.Name = name)
The problem is I get the following compile time error:
Type constraint mismatch. The type
'a
is not compatible with type
C
The type ''a' does not match the type 'C'
Removing inline
from the function definition gives me the following compile time error:
This code is not sufficiently generic. the type variable ^a when ^a:(member get_Name: ^a -> string) could not be generalized because it would escape its scope.
What I am trying to achieve is have a function that takes a generic type with a property of a specific name, "Name" in this case. What am I doing wrong or what am i missing?
The problem is how you're invoking the constrained member - you can't use the i.Name
syntax, but instead must use a more verbose syntax. On the bright side, this enables the signature of the method itself to be inferred, so you don't have to duplicate everything:
let inline filterByName name collection =
collection |> Seq.where(fun i -> (^a : (member Name : string) i) = name)
Note also that you need to use a statically resolved type variable (^a
) instead of a normal generic type variable ('a
).
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