【问题标题】:Return an exception with the Result type返回 Result 类型的异常
【发布时间】:2017-09-08 17:23:32
【问题描述】:

我正在尝试使用 F# 默认存在的错误:异常。

我想用 Result 类型处理错误,但如果我尝试将异常的特殊化(如 ArgumentException)作为错误返回,Visual Studio 会说“这个函数需要太多参数,或者在函数所在的上下文中使用没想到”。

我的来源:

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

【问题讨论】:

  • 你的代码不一致。参数是xy,但是你将ab 分开。你在x 上检查零,那是分母吗?

标签: f#


【解决方案1】:

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

您可以使用:&gt; 运算符安全地将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”所以也许你也在重新定义一些标准类型......

【讨论】:

  • 消息“函数需要太多参数”指的是早期版本的 OP 代码,其中错误案例的构造类似于 Error ArgumentException。显然 OP 更改了代码,但忽略了更改问题文本。
  • @FyodorSoikin 您可以将类型更改为 float -> float -> Result 而不是强制转换为通配符,因为这比 Exception 更有意义
【解决方案2】:

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

  • 在方法签名中,Exception 是泛型 Result 类型的类型参数。
  • 在方法体中,构造返回值时,需要使用Exception类型的实例调用Error

您需要实际调用可能抛出的操作(x/y 通常不会,正如 cmets 中指出的那样),捕获异常,然后返回:

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

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

【讨论】:

  • 我明白你想说,但我不想抛出或检查异常,我只想在 Result 类型中包装一个异常(而不是使用“枚举”)。 F# 没有“new”关键字,所以我应该使用括号来创建对象(我已经编辑了我的帖子)。问题是我无法返回异常的特化,例如 ArgumentException。
  • F# 确实允许您使用 new 关键字创建对象的新实例。我能够使用let e = new System.ArgumentException("y") 创建一个实例(假设您想预先检查除以零)。
  • @Eric 如果我尝试返回“错误 e”,问题是一样的:“这个表达式应该有 'Exception' 类型,但这里有 'ArgumentException' 类型”。
  • 您必须使用:&gt; 转换运算符将ArgumentException 转换为Exception。我刚刚在 F# Interactive 中做了类似的事情:let (e2: Result&lt;string, System.Exception&gt;) = Error (System.ArgumentException("y") :&gt; System.Exception);;
  • 仅供参考,带有正常标志1.0 / 0.0 不会抛出而是返回:inf。甚至0.0 / 0.0 都不会抛出,它变成了nan
猜你喜欢
  • 1970-01-01
  • 2011-03-21
  • 1970-01-01
  • 1970-01-01
  • 2022-12-12
  • 2015-03-12
  • 1970-01-01
  • 1970-01-01
  • 2016-10-27
相关资源
最近更新 更多