Каким был бы идиоматический способ F # писать необязательные параметры?

В контексте библиотеки для генерации случайных кредитных карт было бы неплохо дать пользователю возможность устанавливать некоторые дополнительные параметры для некоторых карт. Возьмем 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 ответ
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"

Существует также опция на основе атрибутов, представленная в

https://github.com/fsharp/fslang-design/blob/master/FSharp-4.1/FS-1027-complete-optional-defaultparametervalue.md

    Добавить комментарий

    Ваш адрес email не будет опубликован. Обязательные поля помечены *