我实现了一个可用于选择函数的 Discriminated Union 类型:

type BooleanCombinator =
    | All
    | Some
    | None
    | AtLeast of int
    | MoreThan of int
    | NotMoreThan of int
    | LessThan of int
    | ExactlyOne
    | ExactlyTwo
    | AllButOne
    | AllButTwo

let boolToInt (b: bool) : int = if b then 1 else 0

let combineBooleans (combinator : BooleanCombinator)
                    (bools      : bool list)
                                : bool =

        let n = List.sumBy boolToInt bools

        match combinator with
        | BooleanCombinator.All -> List.forall id bools
        | BooleanCombinator.Some -> bools |> List.exists id
        | BooleanCombinator.None -> bools |> List.exists id |> not
        | BooleanCombinator.AtLeast i -> n >= i
        | BooleanCombinator.MoreThan i -> n > i
        | BooleanCombinator.NotMoreThan i -> n <= i
        | BooleanCombinator.LessThan i -> n < i
        | BooleanCombinator.ExactlyOne -> n = 1
        | BooleanCombinator.ExactlyTwo -> n = 2
        | BooleanCombinator.AllButOne -> n = bools.Length - 1
        | BooleanCombinator.AllButTwo -> n = bools.Length - 2

这对我来说看起来没问题,但编译器开始将 SomeNone 的所有实例视为属于这个 DU,而不是 Option DU。

我不想遍历我所有的代码,用 Some 替换 Option.Some ,用 None 替换 Option.None

有没有办法告诉编译器不合格的 SomeNone 实际上是 Option.SomeOption.None

或者我应该给这些 DU 案例赋予不同的名称,例如 AtLeastOneExactlyZero

最佳答案

您可以使用 [<RequireQualifiedAccess>] 属性标记您的 DU。

这意味着无论何时在代码中使用案例名称都需要用类型限定案例名称 - 这是您现在在 match 表达式中所做的事情。

这样,不合格的 Some 仍然会被解析为 Option.Some ,尽管您重用了该名称。

知道何时要为 DU 案例使用活泼的名称(例如 NoneYesFailure 等)是一种有用的技术,这本身就会使读者(或编译器,就此而言)模棱两可或混淆。

关于f# - 可以为 Discriminated Union 类型设置默认值吗?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/51334151/

10-12 12:57
查看更多