Let's assume that we have an add function that adds two numbers:
// int -> int -> intlet add a b = a + b
And an another function that converts a string to an integer:
// 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)
With the help of Result.map2 function, we can now do the following:
let okResult = Result.map2 add (tryParseInt "40")(tryParseInt "2")// Ok 42let errorResult = Result.map2 add (tryParseInt "40")(tryParseInt "foobar")// Error "unable to parse 'foobar' to integer"
Example 2
Let's assume that we have the following types:
Latitude
typeLatitude=private Latitude offloatwith// floatmember this.Value =let(Latitude lat)= this in lat// float -> Result<Latitude, string>static member TryCreate (lat :float)=if lat >-90.&& lat <=90.then Ok (Latitude lat)else sprintf "%A is a invalid latitude value" lat |> Error
Longitude
typeLongitude=private Longitude offloatwith// floatmember this.Value =let(Longitude lng)= this in lng// float -> Result<Longitude, string>static member TryCreate (lng :float)=if lng >=-180.&& lng <=180.then Ok (Longitude lng)else sprintf "%A is a invalid longitude value" lng |> Error
Location
typeLocation={ Latitude :Latitude Longitude :Longitude }static member Create lat lng ={ Latitude = lat; Longitude = lng }
Then, we can use the Result.map2 function as below to create the location with validation:
let validLatR = Latitude.TryCreate 13.067439let validLngR = Longitude.TryCreate 80.237617open FsToolkit.ErrorHandlinglet result = Result.map2 Location.Create validLatR validLngR(* Ok {Latitude = Latitude {Value = 13.067439;}; Longitude = Longitude {Value = 80.237617;};} *)
When we try with an invalid latitude value, we'll get the following result:
let invalidLatR = Latitude.TryCreate 200.let result = Result.map2 Location.Create invalidLatR validLngR// Error "200.0 is a invalid latitude value"