traverseResult

Option.traverseResult

Namespace: FsToolkit.ErrorHandling

Function Signature:

('a -> Result<'b,'c>) -> 'a option -> Result<'b option, 'c>

Note that traverse is the same as map >> sequence. See also Option.sequenceResult.

See also Scott Wlaschin's Understanding traverse and sequence.

Examples

Example 1

If we have a value of type string option and want to call the tryParseInt function that we defined in the Result.map2 example, we can achieve it using the traverseResult function as below:

Some "42" |> Option.traverseResult tryParseInt
// Ok (Some 42)

None |> Option.traverseResult tryParseInt
// Ok None

Some "foo" |> Option.traverseResult tryParseInt
// Error "unable to parse 'foo' to integer"

Example 2

The CreatePostRequest type that we defined in Result.map3 example contains a Location option. The corresponding DTO objects would look like this:

type LocationDto = {
  Latitude : float
  Longitude : float
}

type CreatePostRequestDto = {
  Tweet : string
  Location : LocationDto option
}

Let's assume that we have this function to convert a LocationDto to a Location:

// LocationDto -> Result<Location, string>
let locationFromDto (dto : LocationDto) = result {
  let! lat = Latitude.TryCreate dto.Latitude
  let! lng = Longitude.TryCreate dto.Longitude
  return {Location.Latitude = lat; Longitude = lng}
}

Then in order to create a similar function to convert a CreatePostRequestDto to a CreatePostRequest, we can make use of traverseResult as below:

let createPostRequestFromDto (dto : CreatePostRequestDto) = result {
    // Parse the location DTO option to a Location option,
    // returning an error if it's Some and invalid
    let! location =
      dto.Location |> Option.traverseResult locationFromDto

    let! tweet = Tweet.TryCreate dto.Tweet
    return {
      Tweet = tweet
      Location = location
    }
  }

See also the example 2 of ResultOption.map2.

Last updated