如何根据 F# 中许多昂贵计算的 or-else 计算结果

How to calculate a result based on or-else of many expensive computations in F#

假设我有以下伪 C# 代码:

TResult MyMethod()
{
    var firstTry = SomeExpensiveComputation1();
    if (firstTry.IsSuccessful) return firstTry;

    var secondTry = SomeExpensiveComputation2();
    if (secondTry.IsPartiallySuccessful)
    {
        var subTry1 = SomeExpensiveComputationOn2_1(secondTry);
        if (subTry1.IsSuccessful) return subTry1;

        var subTry1 = SomeExpensiveComputationOn2_2(secondTry);
        if (subTry1.IsSuccessful) return subTry1;
    }

    return LastExpensiveComputationThatNeverFails();
}

如果我在 F# 中执行此操作,它将如下所示:

let MyMethod () =
    let firstTry = SomeExpensiveComputation1 ()
    if firstTry.IsSuccessful then firstTry else
        let secondTry = SomeExpensiveComputation2 ()
        if secondTry.IsSuccessful then
            let subTry1 = SomeExpensiveComputationOn2_1 ()
            if subTry1.IsSuccessful then subTry1 else
                let subTry2 = SomeExpensiveComputationOn2_2 ()
                if subTry2.IsSuccessful then subTry2 else LastExpensiveComputationThatNeverFails ()
        else
            LastExpensiveComputationThatNeverFails()

正如您在上面看到的,我不得不重复 LastExpensiveComputationThatNeverFails 两次。这不一定是方法调用,它可以是多行内联计算(例如,尝试从缓存中获取一些值,如果它不存在则计算它。)可以将代码重构为另一个函数,但我仍然不喜欢相同的代码,即使只是一行,也必须编写两次(或更多次),因为它会导致重复和混乱的维护。在 F# 中编写此类代码的正确方法是什么?

我认为将 LastExpensiveComputationThatNeverFails 设为一个本地函数,只要需要结果就可以调用它。

但是,也可以将操作更改为 return Option<_> 并使用内置的组合函数。

let MyMethod () =
  SomeExpensiveComputation1 ()
  |> Option.orElseWith
    ( fun () -> 
        SomeExpensiveComputation2 ()
        |> Option.bind (fun _ -> SomeExpensiveComputationOn2_1 () |> Option.orElseWith SomeExpensiveComputationOn2_2)
    )
  |> Option.orElseWith LastExpensiveComputationThatNeverFails

Option.orElseWith LastExpensiveComputationThatNeverFails 仅当先前的结果为 None 时才执行,失败时将执行此操作。