2016-12-29 1 views
3
type TotalSizeToken = TotalSizeToken with 
    static member TotalSize(_: TotalSizeToken, (a,b,c,d,e)): int = a*b*c*d*e 
    static member TotalSize(_: TotalSizeToken, (a,b,c,d)): int = a*b*c*d 
    static member TotalSize(_: TotalSizeToken, (a,b,c)): int = a*b*c 
    static member TotalSize(_: TotalSizeToken, (a,b)): int = a*b 
    static member TotalSize(_: TotalSizeToken, x: int): int = x 

let inline size_to_total_size x = 
    ((^s) : (static member TotalSize: TotalSizeToken * ^s -> int) TotalSizeToken, x) 

let t = size_to_total_size (1,5) // Error: Expecting a type supporting the operator TotalSize, but given a tuple type. 

Я не ожидал, что аргумент x в size_to_total_size потребует элемента TotalSize. Это похоже на ошибку компилятора.Как получить произведение кортежа int с переменным числом аргументов?

Я не уверен, как заставить это работать. Есть идеи?

ответ

8

Вы пропустили другой тип «шляпа»:

let inline size_to_total_size x = 
    let call (t:^T) = ((^s or ^T) : (static member TotalSize: TotalSizeToken * ^s -> int) t, x) 
    call TotalSizeToken 

Там должно быть два из них, спор передается и один, который представляет собой класс, содержащий перегруженные.

В противном случае он никогда не будет изучать класс, только в кортеже, и такого типа в типе набора не будет.

1
type TotalSizeToken<'u> = TotalSizeToken of 'u with 
    static member TotalSize(x: TotalSizeToken<int*int*int*int*int>): int = 
     match x with TotalSizeToken (a,b,c,d,e) -> a*b*c*d*e 
    static member TotalSize(x: TotalSizeToken<int*int*int*int>): int = 
     match x with TotalSizeToken (a,b,c,d) -> a*b*c*d 
    static member TotalSize(x: TotalSizeToken<int*int*int>): int = 
     match x with TotalSizeToken (a,b,c) -> a*b*c 
    static member TotalSize(x: TotalSizeToken<int*int>): int = 
     match x with TotalSizeToken (a,b) -> a*b 
    static member TotalSize(x: TotalSizeToken<int>): int = 
     match x with TotalSizeToken x -> x 

let inline size_to_total_size x = 
    ((^s) : (static member TotalSize: ^s -> int) x) 

let t = size_to_total_size (TotalSizeToken(1,5)) 

Эта альтернативная форма работает. Есть дополнительный бокс, но с плюсом стороны, я не буду проходить вокруг лямбда повсюду. Как ни странно, это не работает, если size_to_total_size написан как let inline size_to_total_size x = ((^s) : (static member TotalSize: TotalSizeToken< ^s> -> int) x).

Смежные вопросы