Вы должны сделать их stati c членами промежуточного типа:
open System
type T = T with
static member ($) (T, x) = if Double.IsNaN(x) then None else Some (decimal x)
static member ($) (T,(x, y)) =
match (x, y) with
| (x, y) when not(Double.IsNaN(x)) && not (Double.IsNaN(y)) -> Some (decimal x, decimal y)
| (_, _) -> None
let inline parse x = T $ x
// Usage
let a = parse (1. , 2.)
// val a : (decimal * decimal) option = Some (1M, 2M)
let b = parse 1.
// val b : decimal option = Some 1M
Также обратите внимание, что лучше использовать бинарный оператор для отправки также промежуточного типа. Таким образом, вы задерживаете разрешение перегрузки.
Вы также можете использовать именованные функции, но это более многословно.
EDIT Относительно задержки разрешения перегрузки.
First of все, я сказал, чтобы написать это как именованную функцию, вы должны написать ограничения вручную:
let inline parse (x: ^a) =
((^b or ^a) : (static member ($) : ^b -> ^a -> _) T,x)
Обратите внимание, что другой ответ, который был добавлен позже, точно такой же, как этот, единственное отличие является то, что он использует имя ToOption
для члена stati c вместо оператора.
Хорошо, теперь давайте попробуем избавиться от T
, мы можем сделать это до некоторой степени:
type T = T with
static member ($) x = if Double.IsNaN(x) then None else Some (decimal x)
static member ($) ((x, y)) =
match (x, y) with
| (x, y) when not(Double.IsNaN(x)) && not (Double.IsNaN(y)) -> Some (decimal x, decimal y)
| (_, _) -> None
let inline parse (x: ^a) =
let call (_:'b) = ((^b or ^a) : (static member ($) : ^a -> _) x)
call T
Обратите внимание, что мне пришлось создать способ объединения ^b
с T
, поэтому я добавил функцию call
.
Теперь это все еще работает, и это правильное решение который очищает сигнатуру перегрузки и добавляет немного шума в функцию анализа, что во многих сценариях ios является хорошим компромиссом. Но что, если я полностью удаляю параметр ^a
из вызова черты?
let inline parse (x: ^a) =
let call (_:'b) = (^b : (static member ($) : ^a -> _) x)
call T
это не получается с
~vs6086.fsx(11,27): error FS0043: A unique overload for method 'op_Dollar' could not be determined based on type information prior to this program point. A type annotation may be needed.
Known return type: 'b
Known type parameter: < ^a >
Candidates:
- static member T.( $ ) : (float * float) -> (decimal * decimal) option
- static member T.( $ ) : x:float -> decimal option
Почему это так?
Потому что теперь Компилятор F # знает на сайте trait-call все задействованные переменные типа.
До этого последнего изменения ^a
было неизвестно, а ^b
было объединено с T
, но, поскольку другое было неизвестно, перегрузка разрешение было отложено до каждого последующего отдельного вызова функции parse
, что выполнимо, поскольку она объявлена встроенной.
Зная все параметры типа, он пытается применить стандартное разрешение перегрузки Net и завершается неудачно, поскольку 2 кандидата.
Надеюсь, это объяснение имеет смысл.