Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/fsharp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
F# 可以为有区别的联合类型设置默认值吗?_F#_Discriminated Union_Qualified Name - Fatal编程技术网

F# 可以为有区别的联合类型设置默认值吗?

F# 可以为有区别的联合类型设置默认值吗?,f#,discriminated-union,qualified-name,F#,Discriminated Union,Qualified Name,我实现了一个用于选择函数的有区别的联合类型: type BooleanCombinator = | All | Some | None | AtLeast of int | MoreThan of int | NotMoreThan of int | LessThan of int | ExactlyOne | ExactlyTwo | AllButOne | AllButTwo let boolToInt

我实现了一个用于选择函数的有区别的联合类型:

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
类型布尔组合器=
|全部
|一些
|没有
|至少是整数
|超过整数
|不超过整数
|莱斯特尚国际酒店
|精确的
|正好两个
|烯丁酮
|奥尔布托
设boolToInt(b:bool):int=如果是b,则为1,否则为0
let combineBooleans(组合子:布尔组合子)
(布尔:布尔列表)
:bool=
设n=List.sumBy boolToInt bools
匹配组合符
|BooleanCombinator.All->List.forall id bools
|BooleanCombinator.Some->bools |>List.id
|BooleanCombinator.None->bools |>List.exists id |>not
|BooleanCombinator.AtLeast i->n>=i
|BooleanCombinator.MoreThan i->n>i
|布尔组合符.不超过i->nn=1
|BooleanCombinator.ExactlyTwo->n=2
|BooleanCombinator.AllButOne->n=bools.Length-1
|BooleanCombinator.AllButTwo->n=bools.Length-2
在我看来,这是正常的,但编译器开始将
Some
None
的所有实例视为属于此DU,而不是
选项
DU

我不想用
选项替换
部分
。用
选项替换部分
。无

有没有办法告诉编译器,不合格的
部分
实际上是
选项。部分
选项。无


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

在F#中解决名称冲突的一般规则是“最后声明获胜”。由于自定义DU是在
选项
之后声明的,因此它的构造函数
部分
胜过
选项
的构造函数

但此规则提供了一种解决问题的方法:您只需在自定义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
被推断为分别具有类型
Bogus->int
Bogus
,因为它们体内的
一些
指的是
伪。一些
伪.无

函数
f
和值
y
被推断为具有
选项
相关类型,因为它们体内的
Some
None
指的是
Some
函数和我刚才定义的
(| Some | None |)活动模式


当然,这是一种相当老套的恢复现状的方法。这将使编译器信服,但人类仍然很难阅读您的代码。我建议您改名DU的案例。

您可以使用
[]
属性标记DU

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

这样一来,一个不合格的
Some
仍将被解析为
选项。Some
,尽管您重新使用了该名称


这是一种很有用的技巧,可以知道什么时候你想为DU案例使用一个简洁的名称,比如
None
Yes
Failure
等等,这本身就可能让读者(或编译器)感到模棱两可或困惑。

这实际上比我的答案要好。我完全忘记了
RequireQualifiedAccess
> g
g : Bogus -> int

> f
f : 'a option -> int

> x
Bogus

> y
int option