F#Choice类型的用例

时间:2013-05-23 10:47:29

标签: f#

我已经知道F# Choice类型有一段时间了,但是我想不出任何地方我会使用它而不是用有意义的命名案例定义我自己的union type

MSDN文档没有提供太多建议(“有两种选择的活动模式的帮助程序类型。”)并且没有任何示例用法。

我必须遗漏一些东西 - 这种类型相对于自定义联盟的主要优势是什么?

4 个答案:

答案 0 :(得分:9)

在我看来,Choice类型的用例与元组类型的用例非常相似。在任何一种情况下,您通常都希望定义自己更具体的类型,该类型与类型同构(用于选择的自定义DU;用于元组的自定义记录类型)。尽管如此,在有限的范围或非常通用的情况下(良好的命名可能变得困难),拥有匿名变体是很好的。

答案 1 :(得分:4)

当然,对于特定情况,更具体的联合类型可能更好,但是使用一般的Choice联合意味着当使用诸如Workflows,Functors等常规构造时,您的代码可以很好地与其他代码进行网格划分。

IIRC在标准FSharp核心库中没有实现Either Monad(F#lingo中的工作流),但FSharpx库中有一个(虽然我找不到它的构造函数所以我有感谢@MauricioScheffer将我自己推〜choose

从我有限的,主要是C#互操作,F#体验,选择和选项并没有被融入到F#的标准方法中,就像Haskell的Maybe和Either代数数据类型被融入其标准库一样,所以你得不到那么多当你在Haskell中使用它们时,“这是有用的”意义,但它们非常有用。

至于一个例子:在我最近写的一个应用程序中,当我有一个成功的结果时,我从方法返回了Choice1Of2,当出现问题时,我返回了带有错误消息的Choice2Of2 - 是否捕获了异常或者未满足前提条件 - 并在流程控制的工作流程中运行我的代码。这是此联合类型的一个标准用法。

答案 2 :(得分:3)

最佳示例是Async.Catch,您可以返回结果或异常,两者都有意义。

话虽如此,Choice的使用在F#代码中相对有限,并且大多数时候人们使用DU。但是,当您无法定义DU时,可能会使用Choice

与C#交互时,

Choice也可能有更好的行为

答案 3 :(得分:2)

我在尝试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