Возможно ли в F # выделить факторы типа - PullRequest
0 голосов
/ 15 октября 2019

Я использую приведенный ниже бит кода

// Neat method of finding the TryParse method for any type that supports it.
// See https://stackoverflow.com/a/33161245/158285
let inline tryParseWithDefault (defaultVal:'a) text : ^a when ^a : (static member TryParse : string * ^a byref -> bool) = 
    let r = ref defaultVal
    if (^a : (static member TryParse: string * ^a byref -> bool) (text, &r.contents)) 
    then !r 
    else defaultVal  

, но замечаю, что ограничение типа

^a : (static member TryParse : string * ^a byref -> bool

используется дважды. Есть ли способ сделать следующее

constraint Parsable a = ( a : ^a : (static member TryParse : string * ^a byref -> bool)

и использовать Parsable, как

// Neat method of finding the TryParse method for any type that supports it.
// See https://stackoverflow.com/a/33161245/158285
let inline tryParseWithDefault (defaultVal:'a) text : Parsable = 
    let r = ref defaultVal
    if (^a : (Parsable) (text, &r.contents)) 
    then !r 
    else defaultVal  

Ответы [ 2 ]

1 голос
/ 15 октября 2019

Как говорит существующий ответ, вам не нужно явно повторять ограничение в сигнатуре типа, потому что компилятор F # может вывести его. Еще один способ дальнейшего выделения кода, который включает ограничение типа, состоит в том, чтобы просто иметь функцию tryParse, которая вызывает метод TryParse (и имеет ограничение типа), а затем вызывать эту функцию из вашего tryParseWithDefault.

Таким образом, вы отделяете «основную» логику вызова члена от любой дополнительной логики. Когда вы делаете это, вам снова не нужно повторять ограничение, потому что компилятор выводит его:

let inline tryParse text = 
    let mutable r = Unchecked.defaultof<_>
    (^a : (static member TryParse: string * ^a byref -> bool) (text, &r)), r 

let inline tryParseWithDefault (defaultVal:'a) text =
    match tryParse text with 
    | true, v -> v
    | _ -> defaultVal
1 голос
/ 15 октября 2019

Нет никакого способа, о котором я знаю, однако вы можете упростить функцию, позволив F # выводить сигнатуру:

let inline tryParseWithDefault defaultVal text = 
    let r = ref defaultVal
    if (^a : (static member TryParse: string * ^a byref -> bool) (text, &r.contents)) 
    then !r 
    else defaultVal
...