测试值是否是受歧视联合的特定实例

时间:2014-05-12 21:41:42

标签: f#

如果我有一个受歧视的联盟

type Result<'T,'U> =
| Success of 'T
| Failure of 'U

然后我可以创建一个模式匹配函数来测试成功

let success = function
    | Success(_) -> true
    | _ -> false

我可以将其创建为单线,就像这样吗?

let success = fun x -> x = Success(_)

这最后一行没有编译,但我认为它证明了我的意图

4 个答案:

答案 0 :(得分:5)

没有简单的方法可以这样做,但你可以通过反思来做到这一点。使用this answer中的isUnionCase函数,我们可以写:

let success = isUnionCase <@ Success @>

对于这个特殊情况,我认为success函数非常简洁,足以被认定为单行:

let success = function Success _ -> true | _ -> false

正如@Daniel所说,应该公开编译器生成的Is*函数。用户语音上有related suggestion,也许您应该投票,以便在F#4.0中实现。

答案 1 :(得分:4)

编译后的表单为每个案例公开了IsSuccess/IsFailure等属性,但不幸的是,在这种情况下,它们仅在其他.NET语言中可用。你拥有的就是它的好处。

有趣的是,尝试定义这些成员也不会有用:

type Result<'T,'U> =
    | Success of 'T
    | Failure of 'U
    member this.IsSuccess = true //ERROR
  

无法定义成员'IsSuccess',因为名称'IsSuccess'   冲突与工会案例'成功'的默认扩充   这种类型或模块

如果它们存在于F#中,因为无法定义具有相同名称的成员,它们也应该可用。也许拉动请求的候选人?

答案 2 :(得分:0)

您可以创建一个可以帮助您的通用功能:

let ItIsSucess value =
  match value with
  | Success(_) -> true
  | _          -> false

比你能写的......像:

let expr = ...
if ItIsSucess expr than
  "do something"
else
  "do nothing"

你也可以考虑像一个更通用的函数思考,并使用反射来测试任何类型。但这并不容易,我不建议为这个简单的任务做到这一点。反射可能会破坏F#中类型安全的好处,因此请注意是否使用它。

答案 3 :(得分:0)

注意到选项类型 具有IsSomeIsNone属性,我查看了源代码,发现该类型已装饰[<DefaultAugmentation(false)>]。< / p>

将该属性应用于Result类型,我发现我能够定义IsSuccess属性。此属性“关闭为该类型生成的公共语言基础结构(CLI)类生成标准帮助程序成员测试程序,构造函数和访问程序成员”,因此请谨慎使用。

您也可以从Option类型中获取另一个提示,并定义一个Result模块,定义isSuccessisFailure函数:

module Result =
    let isSuccess = function Success _ -> true | _ -> false
    let isFailure = function Failure _ -> true | _ -> false