Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

F# Type Constraint Mismatch when using a constraint on a generic function

Tags:

.net

inline

f#

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?

like image 684
Anish Patel Avatar asked Feb 03 '16 17:02

Anish Patel


1 Answers

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).

like image 196
kvb Avatar answered Nov 15 '22 08:11

kvb