可以为Discriminated Union类型设置默认值吗?

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杜.

我并不想通过我的所有代码替换SomeOption.SomeNoneOption.None.

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

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

Fyo*_*kin 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
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分别,因为SomeNone自己的身体参考Bogus.SomeBogus.None.

功能f和价值y被推断为有Option产权相关的类型,因为SomeNone他们的身体参考Some功能和(|Some|None|)我刚才上面所定义的有效模式.

当然,这是恢复现状的一种相当黑客的方式.这将说服编译器,但人类仍然很难读取您的代码.我建议你重命名你的DU案例.