我实现了一种区分联合类型,该类型将用于选择函数:
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
答案 0 :(得分:6)
解决F#中名称冲突的一般规则是“最后声明获胜”。由于您的自定义DU是在Option
之后声明的,因此其构造函数Some
和None
胜过Option
的构造函数。
但是此规则提供了一种解决问题的方法:您只需要在自定义DU之后“重新声明”声明即可。
type Bogus = Some of int | None
let g = function Some _ -> 42 | None -> 5
let x = Some 42
let inline Some a = Option.Some a
let inline None<'a> = Option.None : 'a option
let (|Some|None|) = function | Option.Some a -> Some a | Option.None -> None
let f = function Some _ -> 42 | None -> 5
let y = Some 42
如果您检查以上代码中的g
,x
,f
和y
的类型:
> g
g : Bogus -> int
> f
f : 'a option -> int
> x
Bogus
> y
int option
推断函数g
和值x
分别具有类型Bogus -> int
和Bogus
,因为它们中的Some
和None
请参阅Bogus.Some
和Bogus.None
。
推断函数f
和值y
具有与Option
相关的类型,因为它们中的Some
和None
引用了{{ 1}}函数和我在上面定义的Some
活动模式。
当然,这是一种恢复现状的简单方法。这将使编译器信服,但是人类仍然很难阅读您的代码。我建议您改用DU的案例。
答案 1 :(得分:4)
您可以使用[<RequireQualifiedAccess>]
属性标记您的DU。
这意味着您每次在代码中使用案例名称时,都必须使用类型来限定案例名称-现在您仍可以在match
表达式中进行此操作。
这样,尽管您重用了名称,但不合格的Some
仍将被解析为Option.Some
。
知道何时要为DU案例使用简明的名称是一种有用的技术,例如None
,Yes
,Failure
等-本身就是模棱两可或会使读者(或编译器)感到困惑。