有没有一种方法可以快速检查已区分的并集值的类型,而无需使用匹配项

时间:2020-05-16 13:39:52

标签: f#

让我说我有这种类型:

type ResultInfo =
| Success
| Error of (HttpStatusCode * string)

和一个返回ResultInfo类型的“结果”的函数

有没有办法做类似的事情:

if result is type Success then ...

因为有时我只想知道类型,并且在只需要快速检查的情况下,match语法可能会有点繁琐

3 个答案:

答案 0 :(得分:3)

您不能进行类型测试,因为联合用例不是真正的类型-它是一个联合类型(如C中的联合),带有一个标记,表明它是哪种情况。

这就是为什么您不能做这样的事情:

type MoreSuccess = MoreSuccess of Success //type Success is not defined

因此,您无法执行运行时类型检查。但是,对于实现结构相等的成员,可以直接进行比较。因此,

if result = Success then
    printfn "Success!"
else
    printfn "Boo"

是完全有效的,并且也清晰易读。 如果您真的想使用if表达式,则更紧凑的方法是定义一个内联函数,如下所示:

if (function Error _ -> true | _ -> false) result then
    printfn "Error"

有趣的是,编译器将生成扩展属性,如IsSuccessIsError,这些属性可以按预期工作,但是,它们是与来自C#和VB等其他语言的DU互操作的好处,很不幸在F#中不可见。

答案 1 :(得分:2)

您可以编写Option.isSome之类的帮助程序模块

module ResultInfo =

    let isSuccess = function
        | Success -> true
        | Error _ -> false

    let isError = function
        | Success -> false
        | Error _ -> true

if result |> ResultInfo.isSuccess then
    ...

或将属性/功能附加到您的类型

type ResultInfo =
    | Success
    | Error of (HttpStatusCode * string)
    member self.IsSuccess =
        match self with
        | Success -> true
        | Error _ -> false

if result.IsSuccess then
    ...

我总是喜欢明确指定所有联合用例,以便通过添加新用例将生成编译器警告。如果仅匹配Success并用_处理所有其他并集情况,可能会导致潜在的错误,因为您没有得到编译器警告,甚至可能会忘记处理该情况。

答案 2 :(得分:0)

您可以将字符串值与类似这样的函数进行比较:

let sameStrings ut1 ut2 =
    let firstPart (str:string) = str.Split([|' '|])
    let nameString = string >> firstPart
    nameString ut1 = nameString ut2

然后有一个if语句,例如if sameStrings Success a then

下面的示例用法和输出(请注意,这不会比较实际的错误值,但是如果您想执行此操作,则应该只能使用字符串比较):

type ResultInfo =
    | Success
    | Error of (int * string)

let printSameAs ut1 ut2 = 
    printfn "%A - match %A: %b" ut1 ut2 (sameStrings ut1 ut2)

let a = Success
let b = Error (404,"Not Found")

printSameAs a Success
printSameAs b Success
printSameAs a (Error (0,""))
printSameAs b (Error (0,""))

有输出:

Success - match Success: true
Error (404, "Not Found") - match Success: false
Success - match Error (0, ""): false
Error (404, "Not Found") - match Error (0, ""): true