ForNeVeR
ForNeVeR

Reputation: 6955

Inline function and type extension

Consider I have two different library types:

type Foo = { foo : string }
type Bar = { bar : int32 }

I want to implement generic function zoo that will work for either Foo or Bar instances. And I cannot change Foo and Bar because they are part of library code.

Here's my first attempt using type extensions and inline function as explained here:

// Library.fs
module Library

type Foo = { foo : string }
type Bar = { bar : int32 }

// Program.fs
type Foo with
    static member zoo (f : Foo) = "foo"

type Bar with
    static member zoo (b : Bar) = "bar"

let inline zoo (x : ^t) =
    (^t : (static member zoo : ^t -> string) x)

let f = zoo { foo = "1" } // error FS0001: The type 'Foo' does not support the operator 'zoo'

Why don't inline function definition relies on type extensions? How could I solve my problem without changing of the initial Foo and Bar type definitions?

Upvotes: 7

Views: 337

Answers (2)

Gus
Gus

Reputation: 26174

Use method overload.

The problem with extension methods is that they are not taken into account when solving member constraints .

So you can use method overload, as shown already in your own answer or you can go further and create an inline generic function by using an intermediate type and an intermediate method (in this case an operator for simplicity) to do the trick:

type T = T with
    static member ($) (T, x:Foo) = "foo"
    static member ($) (T, x:Bar) = "bar"

let inline zoo x = T $ x

let f = zoo { foo = "1" }

Here you have more details about how this works.

Be aware that this function will be inlined, so for instance you won't be able to call it from C#, if this is required don't use a function, use simple and standard method overload.

Upvotes: 11

ForNeVeR
ForNeVeR

Reputation: 6955

The best thing I could get so far is

type Ext =
    static member zoo (f : Foo) = "foo"
    static member zoo (b : Bar) = "bar"

let f = Ext.zoo { foo = "1" } // "foo"
let b = Ext.zoo { bar = 2 } // "bar"

It is not the best and not very generic solution but at least it works.

Upvotes: 1

Related Questions