Вариант использования для выбора типа 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