【问题标题】:Performing Calculations on F# option types对 F# 选项类型执行计算
【发布时间】:2015-04-23 18:28:25
【问题描述】:

我正在尝试编写一些通过返回双选项而不是双精度来处理错误的函数。其中许多函数相互调用,因此将双重选项作为输入以输出其他双重选项。问题是,我不能用双精度选项来做我可以用双精度来做的事情——像使用'+'添加它们这样简单。

例如,一个函数将两个双精度数相除,并返回一个双精度选项,没有除以零错误。然后另一个函数调用第一个函数并为其添加另一个双重选项。

请告诉我是否有办法做到这一点,或者我是否完全误解了 F# 选项类型的含义。

【问题讨论】:

  • 尝试添加一些代码示例,说明您要实现什么以及遇到什么错误
  • Some(1.0) + Some(1.0) 这样无辜的东西是行不通的。如果它真的不起作用,那么我就不能真正使用它,因为我有很多接受双重选项并返回双重选项的函数,它们都依赖于彼此来做一些数学运算。
  • 您正在寻找的是一个选项工作流程。看看this thread
  • ...或者直接使用Option.bind

标签: f# options


【解决方案1】:

这称为提升 - 您可以编写函数以通过两个选项提升另一个函数:

let liftOpt f o1 o2 = 
        match (o1, o2) with
        | (Some(v1), Some(v2)) -> Some(f v1 v2)
        | _ -> None

然后您可以提供要应用的功能,例如:

let inline addOpt o1 o2 = liftOpt (+) o1 o2

【讨论】:

  • 您实际上可以更进一步使代码更具可读性:定义 liftOpt 就像这里所做的那样,然后(在非常非常本地执行此操作)shadow +let (+) o1 o2 = liftOpt(+) o1 o2 这样的东西。现在你可以写let x, y = Some 3.0, Some 2.0 然后x + y
  • @DanielFabian 好提示,这样做的好地方(IMO)是将提升的(+) 放在module Option 中,以扩展默认的Option。然后只有在open Option 之后,你才会在范围内提升(+) :)
【解决方案2】:

如上所述,liftA2 将提供一种通用方法,将任何可处理 double 参数的函数“提升”到可处理 double option 参数的函数。

但是,在您的情况下,您可能必须自己编写特殊函数来处理您提到的边缘情况

let (<+>) a b =
    match (a, b) with
    | (Some x, Some y) -> Some (x + y)
    | (Some x, None)   -> Some (x)
    | (None, Some x)   -> Some (x)
    | (None, None)     -> None

请注意,liftA2 不会自动将您要添加NoneSome(x) 的情况放入。

除法的liftA2方法也需要一些特殊处理,但它的结构一般是我们自己写的

let (</>) a b =
    match (a, b) with
    | (Some x, Some y) when y <> 0.0d -> Some (x/y)
    | _ -> None

你可以像这样使用这些函数

Some(2.0) <+> Some(3.0) // will give Some(5.0)
Some(1.0) </> Some(0.0) // will give None

另外,严格来说,lift 被定义为“高阶函数”——接受一个函数并返回另一个函数的东西。

所以它看起来像这样:

let liftOpt2 f =
    (function a b ->
        match (a, b) with
        | (Some (a), Some (b)) -> f a b |> Some
        | _ -> None)

【讨论】:

    【解决方案3】:

    最后,我意识到我真正需要的是 Option.get 函数,它只接受一个 'a 选项并返回一个 'a。这样,我可以进行模式匹配,并返回我想要的值。

    【讨论】:

      【解决方案4】:

      在这种情况下,您可能需要考虑 Nullables 而不是 Options,原因有两个:

      • Nullables 是值类型,而 Options 是引用类型。如果您有大量这些双精度数的集合,则使用 Nullables 会将数字保留在堆栈中,而不是将它们放在堆中,从而可能会提高您的性能。
      • Microsoft 提供了一组内置的 Nullable Operators,它们可以让您直接对 nullables 执行数学运算,就像您尝试使用选项一样。

      【讨论】:

        猜你喜欢
        • 2014-01-05
        • 2020-10-11
        • 2023-04-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-11-07
        • 2012-09-25
        相关资源
        最近更新 更多