2013-05-23 3 views
12

Я знаю тип F# Choice, но не могу придумать ни одного места, которое я использовал бы, вместо определения моего собственного union type со значимыми именованными случаями.Вариант использования для F # Тип выбора

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

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

+1

https://github.com/fsharp/fsharpx/blob/master/tests/FSharpx.Tests/ChoiceTests.fs https://github.com/ fsharp/fsharpx/blob/master/tests/FSharpx.Tests/ValidationTests.fs https://github.com/fsharp/fsharpx/blob/master/tests/FSharpx.Tests/ValidationExample.fs –

+2

Что похоже на Haskell's Либо http : //hackage.haskell.org/packages/archive/base/latest/doc/html/Data-Either.html –

ответ

9

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

+1

Спасибо, я не считал сходство с кортежами, особенно в отношении именования в родовых ситуациях. – Akash

+1

Однако, с кортежами, мне почти никогда не приходится обращаться к элементам через fst или snd, потому что я могу сопоставить шаблон напрямую с более значимыми именованными значениями. Он немного более неуклюжим с выбором. – Akash

3

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

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

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

+0

Незначительная коррекция: это ['Async.Catch'] (http://msdn.microsoft.com/ru -us/library/ee353899.aspx), а не 'Async.Try'. –

+0

@JackP. исправлено с помощью редактирования –

4

Конечно, более конкретный типа союза может быть хорошо для конкретной ситуации, но имеющие общий Выбор союза означает, что ваш код может хорошо сцепляется с другим кодом при использовании общих конструкций, таких как Workflows, функторы и т.д.

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

Из моего ограниченного, в основном, C# interop, опыта F #, выбора и опции не запекаются в стандартных методах F # так же, как Haskell's Maybe, и любые алгебраические типы данных запекаются в его стандартные библиотеки, поэтому вы не получите большая часть «этого полезного» смысла при использовании их в F #, как вы могли бы в Haskell, но они весьма полезны.

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

+1

См. Https://github.com/fsharp/fsharpx/blob/master/tests/FSharpx.Tests/ChoiceTests.fs#L69 –

+1

@MauricioScheffer ах, это 'выбрать'! Благодаря! – paul

+0

[ExtCore] (https://nuget.org/packages/ExtCore/) также содержит реализацию рабочего процесса «Либо» (так называемый «выбор») и множество полезных функций для работы со значениями выбора: https: // github .com/jack-pappas/ExtCore –

0

Я заметил, что это значение при попытке enforce the creation of a discriminated union value via a dedicated function and Active Patterns.

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

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 
Смежные вопросы