F#中的结果和领域设计

时间:2018-12-11 07:16:32

标签: f#

我对设计和使用结果有一个快速的问题。 我已经阅读了FSharpForFunAndProfit上有关Railway Oriented Programming的出色文章,它确实符合我的需要,因为我需要访问数据库中的数据,并且某些数据可能不可用(因此会产生错误)。 / p>

假设我拥有以下域

type Main = A * B
type B =
{ B1 of float
  B2 of string } // or any type, just took 2 simple ones)

如果我不使用Result,则可以轻松访问main:Main的所有内容

let a = main |> fst
let b1 = (snd B).B1

但是,假设我要使用类似这样的函数来创建Main

val createMain : x:sometihng -> Result<Main, 'T>

然后我知道要访问该主对象中的A(在Result.Ok情况下),我可以使用以下代码:

    let fail x = 
        Result.Error x

    let succeed x = 
        Result.Ok x

    let either successFunc failureFunc twoTrackInput =
        match twoTrackInput with
        | Result.Ok s -> successFunc s
        | Result.Error f -> failureFunc f   

    let map f = 
        either (f >> succeed) fail

在这种情况下,我可以编写以下内容:

let a = main |> map fst

我会得到一个

Result<A, 'T>

但是我如何轻松访问b1? 我知道我可以编写类似

的函数
let getB1 main =
    match main with
    | Result.Ok -> (snd main).B1
    | Result.Error t -> Result.Error t

但是,我将需要为每个参数编写一个函数,这非常不方便。

1 个答案:

答案 0 :(得分:3)

您需要编写一些函数,类型为Main,并将其映射为Result。

换句话说,只需编写一堆对您的基本类型进行操作的函数,然后将它们适当地映射/绑定到您的Result类型。

因此,无论您想做什么,都编写一个将其执行为基本类型的函数。然后,在您具有“结果”类型的级别,将功能映射到它。

因此,在较高级别上,您输入结果并输出不同的结果。在较低级别,您可以使用基本类型。