Вариант использования для выбора типа F #

Я некоторое время знал о F # Choice, но не могу думать о каком-либо месте, которое я использовал бы, вместо того, чтобы определять свой собственный тип объединения со значимыми именованными случаями.

Документация MSDN не предлагает много советов ( "Вспомогательные типы для активных шаблонов с двумя вариантами" ) и не имеет каких-либо примеров использования.

Мне нужно что-то упустить - каковы основные преимущества этого типа над пользовательским соединением?

Ответ 1

По-моему, варианты использования для типа Choice весьма похожи на варианты использования для типов кортежей. В любом случае вы часто захотите определить свой собственный более специфический тип, который изоморфен типу (пользовательский DU для выбора, тип пользовательской записи для кортежей). Тем не менее, в ограниченных областях или в очень общих ситуациях (когда хорошее присвоение имен может стать трудным), приятно иметь анонимные варианты.

Ответ 2

Разумеется, более конкретный тип объединения может быть приятным для конкретной ситуации, но наличие общего объединения Choice означает, что ваш код может хорошо взаимодействовать с другим кодом при использовании общих конструкций, таких как Workflows, Functors и т.д.

IIRC там нет реализации Либо Monad (Workflow в F # lingo) в стандартной библиотеке FSharp Core, но есть одна в библиотеке FSharpx (, хотя я не мог найти конструктор для нее, поэтому я чтобы свернуть мой собственный, благодаря @MauricioScheffer, чтобы поместить меня в choose).

Из моего ограниченного, в основном совпадения С#, F # experience, Choice и Option не запекаются в стандартных методах F # так же, как Haskell. Возможно, и любые алгебраические типы данных запекаются в его стандартные библиотеки, так что вы не получите столько же "это полезно", когда вы используете их в F #, как в Haskell, но они весьма полезны.

Как и в примере: в приложении, которое я недавно написал, я вернул Choice1Of2 из методов, когда у меня был успешный результат, и Choice2Of2 с сообщением об ошибке, когда что-то пошло не так: исключение исключение или предварительное условие не выполняется - и запустил мой код в Workflow для управления потоком. Это стандартное использование этого типа объединения.

Ответ 3

Лучший пример: Async.Catch, где вы возвращаете результат или исключение, оба из которых имеют смысл.

Сказав это, использование Choice относительно ограничено в коде F #, и большую часть времени люди используют DU. Тем не менее, Choice может использоваться, если вас не беспокоит определение DU.

Choice может также иметь лучшее поведение при взаимодействии с С#

Ответ 4

Я наблюдал это значение при попытке принудительно создать дискриминационное значение объединения через выделенную функцию и активные шаблоны.

Вот пример, который был опубликован:

module File1 =

    type EmailAddress = 
        private
        | Valid   of string 
        | Invalid of string

    let createEmailAddress (address:System.String) =
        if address.Length > 0
        then Valid    address 
        else Invalid  address

    // Exposed patterns go here
    let (|Valid|Invalid|) (input : EmailAddress) : Choice<string, string>  = 
        match input with
        |Valid str -> Valid str
        |Invalid str -> Valid str

module File2 =

    open File1

    let validEmail = Valid "" // Compiler error

    let isValid = createEmailAddress "" // works

    let result = // also works
        match isValid with
        | Valid x -> true
        | _       -> false