Sol*_*lma 3 f# qualified-name discriminated-union
我实现了一个用于选择函数的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
Run Code Online (Sandbox Code Playgroud)
这看上去好了给我,但编译器开始看的所有实例Some,并None为属于代替这个杜,Option杜.
我并不想通过我的所有代码替换Some用Option.Some和None用Option.None.
有没有办法告诉编译器不合格的Some和None实际上是Option.Some和Option.None?
或者我应该给这些DU案例赋予不同的名称,比如AtLeastOne和ExactlyZero
解决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
Run Code Online (Sandbox Code Playgroud)
如果你检查的类型g,x,f,并y在上面的代码:
> g
g : Bogus -> int
> f
f : 'a option -> int
> x
Bogus
> y
int option
Run Code Online (Sandbox Code Playgroud)
功能g和价值x被推断为有型Bogus -> int,并Bogus分别,因为Some和None自己的身体参考Bogus.Some和Bogus.None.
功能f和价值y被推断为有Option产权相关的类型,因为Some和None他们的身体参考Some功能和(|Some|None|)我刚才上面所定义的有效模式.
当然,这是恢复现状的一种相当黑客的方式.这将说服编译器,但人类仍然很难读取您的代码.我建议你重命名你的DU案例.
| 归档时间: |
|
| 查看次数: |
108 次 |
| 最近记录: |