В контексте библиотеки для генерации случайных кредитных карт было бы неплохо дать пользователю возможность устанавливать некоторые дополнительные параметры для некоторых карт. Возьмем Visa. Доступны две длины: 13 или 16 цифр.
В C # обычная реализация:
enum VisaLengthOptions
{
Thirteen,
Sixteen
}
public static string GenerateVisa(VisaLengthOptions length = VisaLengthOptions.Sixteen) {
if (length == VisaLengthOptions.Thirteen) return "4000000000001";
if (length == VisaLengthOptions.Sixteen) return "4000000000000001";
return "";
}
Поскольку F # не поддерживает необязательные параметры (по причинам каррирования и простоты (обратите внимание, что это можно сделать, поскольку это сделал ocaml)). Каким будет наиболее идиоматичный способ написать это на F #?
Вот предположение:
type VisaLengthOptions =
| Thirteen = 0
| Sixteen = 1
let constructVisa length =
match length with
| VisaLengthOptions.Thirteen -> "4000000000001"
| VisaLengthOptions.Sixteen -> "4000000000000001"
| _ -> ""
let generateVisa () = constructVisa VisaLengthOptions.Sixteen
Таким образом, нет необязательных параметров и две функции не могут иметь одно и то же имя даже с разными подписями. Что не так с этим фрагментом?
Мы хотим, чтобы в нашей библиотеке был действительно доступный для обнаружения API. Поэтому мы хотели бы избежать использования двух разных имен для одной и той же логики. Должны ли мы следовать map
и map2
и идет generateVisa и generateVisa2? или как map
и mapi
и идет generateVisa и generateVisaL? Есть ли один настоящий способ F #?
Хорошим примером в мире .net является Расколоть.
1 ответ
Во-первых, я не думаю, что вам нужно там перечисление, но у меня нет полного контекста вашего фактического использования, в моих примерах используется Discriminated Union, а не перечисление.
Я не уверен, что это идиоматично, но вот 2,5 способа сделать это.
type VisaLengthOptions =
| Thirteen
| Sixteen
let generateVisa =
function
| Some Thirteen -> "4000000000001"
| Some Sixteen
| None -> "4000000000000001"
type Generator() =
member __.GenerateVisa(?visaLength) =
let visaLength = defaultArg visaLength Sixteen
match visaLength with
| Thirteen -> "4000000000001"
| Sixteen -> "4000000000000001"
Существует также опция на основе атрибутов, представленная в