使用Result类型返回异常

时间:2017-09-08 17:23:33

标签: f#

我正在尝试使用F#默认的错误:例外。

我想用Result类型处理错误,但是如果我尝试返回Exception的特化,比如ArgumentException,就像错误一样,Visual Studio说“这个函数需要太多的参数,或者在一个函数的上下文中使用不期望“。

我的来源:

let division (x: float) (y: float): Result<float, Exception> =
    if x = 0.0 then
        Error (ArgumentException ())
    else
        Ok (x / y)

2 个答案:

答案 0 :(得分:4)

您的代码存在的问题是新创建的ArgumentException的类型与您在类型签名中指定的Exception类型不同。

您可以使用ArgumentException运算符安全地Exception :>,但F#不会自动插入强制转换,因此您必须自己编写:

let division (x: float) (y: float): Result<float, Exception> =
    if x = 0.0 then
        Error (ArgumentException () :> Exception)
    else
        Ok (x / y)

实际上,F#甚至可以从类型注释中推断出目标类型,所以你可以只写:

Error (ArgumentException () :> _)

PS:我看到你说你得到的“这个函数需要太多的参数”错误。这很奇怪,也许你的情况会有更多的事情发生。我在尝试您的代码时遇到的错误是“此表达式应该具有Exception类型,但是ArgumentException”所以也许您也在重新定义一些标准类型...

答案 1 :(得分:3)

你混淆了类型和值(更新:这个答案主要是指你帖子的第一个版本,TomasP的答案更适合更新的代码)

  • 在方法签名中,Exception是通用Result类型的类型参数。
  • 在方法正文中,当您构建返回值时,需要使用Error类型的实例调用Exception

你需要实际调用可能抛出的操作(x/y通常不会,如评论中所指出的),捕获异常,然后返回:

let division (x: float) (y: float): Result<float, Exception> =
    try
        let result = SomethingThatCouldThrow x y
        Ok result
    with 
    | e -> Error e

顺便说一句,我不明白你的目标是“使用F#默认的错误:异常。” .Net默认处理错误条件是例外,是的。但是你在这里返回的是一个包装异常的类(在错误的情况下)。