Duck typing with type provider instances

128 views Asked by At

I am writing an F# script to operate on tables in a database. All of the tables have a Guid Id property. I want to make use of duck typing to refer to this ID in several places.

Take for example this function:

let inline getAllIds<'a when 'a : (member Id : Guid with get)
                        and 'a : not struct> (table : Table<'a>) =
    table |> Seq.map (fun x -> x.Id)

I had hoped that the when 'a : (member Id : Guid with get) constraint would allow me to use the Id property on a table record, but I get a type inference error ('a type annotation may be needed' etc).

Furthermore, if I try to pass in a table that doesn't have a Guid Id property to the function, it correctly complains that it does not support the operator get_Id. This seems to indicate to me that I have got the syntax right but might need an additional constraint somewhere. Is what I want to do possible?

(I know that I can just pass a function into this function to retrieve the ID... but where's the fun in that?!)

1

There are 1 answers

1
ildjarn On BEST ANSWER

I'll maintain that this is a duplicate, but here's the exact code you need to get going:

let inline getAllIds< ^a when ^a : not struct> (table : Table< ^a>) =
    table |> Seq.map (fun x -> (^a : (member Id : Guid with get) x))

Alternatively, the following syntax can be used instead:

let inline getAllIds< ^a when ^a : not struct> (table : Table< ^a>) =
    table |> Seq.map (fun x -> (^a : (member get_Id : unit -> Guid) x))

IIRC, the latter syntax is required when using a pre-3.0 F# compiler.