Risultati

Il Result<'T,'TFailure> tipo consente di scrivere codice a tolleranza di errore che può essere composto.

Sintassi

// 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

Osservazioni:

Vedere il Result modulo per i combinatori predefiniti per .Result digitare.

Si noti che il tipo di risultato è un'unione discriminata struct. La semantica di uguaglianza strutturale si applica qui.

Il Result tipo viene in genere usato nella gestione degli errori monadic, spesso definita programmazione orientata alla ferrovia all'interno della community di F#. L'esempio semplice seguente illustra questo approccio.

// 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: {req.Name} Email {req.Email}"  
    | Error e -> printfn $"Error: {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: {req.Name} Email {req.Email}"  
    | Error e -> printfn $"Error: {e}"
    // Prints: "Error: No email from bananas.com is allowed."

test()

Come si può notare, è piuttosto facile concatenare varie funzioni di convalida se si forzano tutti a restituire un oggetto Result. In questo modo è possibile suddividere funzionalità come questa in piccoli pezzi che sono componibili come sono necessari. Questo ha anche il valore aggiunto di applicare l'uso di criteri di ricerca alla fine di un ciclo di convalida, che a sua volta impone un livello superiore di correttezza del programma.

Vedere anche