我实现了一个可用于选择函数的 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
这对我来说看起来没问题,但编译器开始将
Some
和 None
的所有实例视为属于这个 DU,而不是 Option
DU。我不想遍历我所有的代码,用
Some
替换 Option.Some
,用 None
替换 Option.None
。有没有办法告诉编译器不合格的
Some
和 None
实际上是 Option.Some
和 Option.None
?或者我应该给这些 DU 案例赋予不同的名称,例如
AtLeastOne
和 ExactlyZero
最佳答案
您可以使用 [<RequireQualifiedAccess>]
属性标记您的 DU。
这意味着无论何时在代码中使用案例名称都需要用类型限定案例名称 - 这是您现在在 match
表达式中所做的事情。
这样,不合格的 Some
仍然会被解析为 Option.Some
,尽管您重用了该名称。
知道何时要为 DU 案例使用活泼的名称(例如 None
、 Yes
、 Failure
等)是一种有用的技术,这本身就会使读者(或编译器,就此而言)模棱两可或混淆。
关于f# - 可以为 Discriminated Union 类型设置默认值吗?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/51334151/