Computation Expression

Validation Computation Expression

Namespace: FsToolkit.ErrorHandling

The Validation type is defined as:

type Validation<'a,'err> = Result<'a, 'err list>

This CE can take advantage of the and! operator to join multiple error results into a list.

Examples:

// string -> Result<int, string>
let tryParseInt (str: string) =
  match System.Int32.TryParse str with
  | true, x -> Ok x
  | false, _ ->
    Error (sprintf "unable to parse '%s' to integer" str)

Example 1

The example from Validation.map3 can be solved using the validation computation expression as below:

// Validation<int, string>
let addResult = validation {
  let! x = tryParseInt "35"
  and! y = tryParseInt "5"
  and! z = tryParseInt "2"
  return add x y z
}
// Ok 42

Validation "Gotchas"

If you place any 'let!' after your 'and!'s, you will lose out on your error joining

// Validation<int, string>
let addResult = validation {
    let! x = tryParseInt "1"
    and! y = tryParseInt "str1"
    let! z = tryParseInt "str2"
    return x + y + z
}
// Error ["unable to parse 'str1' to integer"]

Combining CE's

Sometimes you need to break apart your computational expressions for readability. You can still join error results from separate validation expressions.

// use existing code found above

// Validation<int, string>
let addResult1 = validation {
    let! x = tryParseInt "1"
    and! y = tryParseInt "str1"
    return x + y
}
// Error ["unable to parse 'str1' to integer"]

// Validation<int, string>
let addResult2 = validation {
    let! x = tryParseInt "1"
    and! y = tryParseInt "str2"
    return x + y
}
// Error ["unable to parse 'str2' to integer"]

let combinedResult = 
    validation {
        let! x = addResult1
        and! y = addResult2
        return x + y
    }
    
// Error ["unable to parse 'str1' to integer"
//        "unable to parse 'str2' to integer"]

Last updated