結果Results

F# 4.1 以降では、構成可能なエラートレラントコードを記述するために使用できる Result<'T,'TFailure> 型があります。Starting with F# 4.1, there is a Result<'T,'TFailure> type which you can use for writing error-tolerant code which can be composed.

構文Syntax

// The definition of Result in FSharp.Core
[<StructuralEquality; StructuralComparison>]
[<CompiledName("FSharpResult`2")>]
[<Struct>]
type Result<'T,'TError> =
    | Ok of ResultValue:'T
    | Error of ErrorValue:'TError

RemarksRemarks

結果の型は、4.1 でF#導入された別の機能である構造体の判別共用体であることに注意してください。Note that the result type is a struct discriminated union, which is another feature introduced in F# 4.1. ここでは構造的等値セマンティクスが適用されます。Structural equality semantics apply here.

Result の種類は、通常、monadic のエラー処理で使用されます。これは、 F#コミュニティ内では、"フロント指向" プログラミングと呼ばれることがよくあります。The Result type is typically used in monadic error-handling, which is often referred to as Railway-oriented Programming within the F# community. 次の簡単な例は、この方法を示しています。The following trivial example demonstrates this approach.

// Define a simple type which has fields that can be validated
type Request =
    { Name: string
      Email: string }

// Define some logic for what defines a valid name.
//
// Generates a Result which is an Ok if the name validates;
// otherwise, it generates a Result which is an Error.
let validateName req =
    match req.Name with
    | null -> Error "No name found."
    | "" -> Error "Name is empty."
    | "bananas" -> Error "Bananas is not a name."
    | _ -> Ok req

// Similarly, define some email validation logic.
let validateEmail req =
    match req.Email with
    | null -> Error "No email found."
    | "" -> Error "Email is empty."
    | s when s.EndsWith("bananas.com") -> Error "No email from bananas.com is allowed."
    | _ -> Ok req

let validateRequest reqResult =
    reqResult
    |> Result.bind validateName
    |> Result.bind validateEmail

let test() =
    // Now, create a Request and pattern match on the result.
    let req1 = { Name = "Phillip"; Email = "phillip@contoso.biz" }
    let res1 = validateRequest (Ok req1)
    match res1 with
    | Ok req -> printfn "My request was valid! Name: %s Email %s" req.Name req.Email
    | Error e -> printfn "Error: %s" e
    // Prints: "My request was valid!  Name: Phillip Email: phillip@consoto.biz"

    let req2 = { Name = "Phillip"; Email = "phillip@bananas.com" }
    let res2 = validateRequest (Ok req2)
    match res2 with
    | Ok req -> printfn "My request was valid! Name: %s Email %s" req.Name req.Email
    | Error e -> printfn "Error: %s" e
    // Prints: "Error: No email from bananas.com is allowed."

test()

ご覧のように、すべてを強制的に Resultを返す場合は、さまざまな検証関数を連結するのが非常に簡単です。As you can see, it's quite easy to chain together various validation functions if you force them all to return a Result. これにより、このような機能を、必要に応じてコンポーザブルな小さな部分に分割できます。This lets you break up functionality like this into small pieces which are as composable as you need them to be. これには、検証のラウンドの最後にパターン一致の使用を強制するための追加の値も含まれます。これにより、より高度なプログラムの正確性が適用されます。This also has the added value of enforcing the use of pattern matching at the end of a round of validation, which in turns enforces a higher degree of program correctness.

関連項目See also