2015-10-02 21 views
7

Rozważmy mam dwie różne bibliotecznych typy:Inline funkcja i typ rozszerzenie

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

Chcę zaimplementować funkcję rodzajowe zoo który będzie działał zarówno dla Foo lub Bar przypadkach. Nie mogę zmienić Foo i Bar, ponieważ są one częścią kodu biblioteki.

Oto moja pierwsza próba z wykorzystaniem rozszerzeń typu i funkcji inline jak wyjaśniono 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' 

Dlaczego nie inline definicja funkcja polega na rozszerzeniach typu? Jak mogę rozwiązać problem bez zmiany początkowych definicji typów Foo i Bar?

Odpowiedz

11

Użyj metody przeciążenia.

Problem z metodami rozszerzającymi polega na tym, że nie są one brane pod uwagę przy solving member constraints.

Można więc użyć przeciążenia metody, jak pokazano już we własnej odpowiedzi lub można przejść dalej i utworzyć wbudowaną funkcję generyczną za pomocą pośredniego typu i pośredniej metody (w tym przypadku operator dla uproszczenia), aby wykonać 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" } 

Tutaj masz more details o tym, jak to działa.

Należy pamiętać, że ta funkcja będzie wstawiona, więc na przykład nie będzie można jej wywołać z języka C#, jeśli jest to wymagane, nie należy korzystać z funkcji, należy użyć prostej i standardowej metody przeciążania.

1

Najlepszą rzeczą, jaką mogę tak daleko jest

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" 

To nie jest najlepszym rozwiązaniem i nie bardzo ogólne, ale przynajmniej działa.

Powiązane problemy