- Notifications
You must be signed in to change notification settings - Fork 104
Closed
Description
Description
Not directly related to #388
But more about the newly released .NET + F# 5.0. The idea would be to provide a dedicated CE builder for validation types supporting the and! keyword.
Sources:
- https://devblogs.microsoft.com/dotnet/announcing-f-5/#applicative-computation-expressions
- https://gist.githubusercontent.com/cartermp/8540e3fb1edf647f3c7ee8e4352c5941/raw/0c6893a68499499eca517118d3db80c379fc8799/fs5-applicatives.fsx
// First, define a 'zip' function module Result = let zip x1 x2 = match x1,x2 with | Ok x1res, Ok x2res -> Ok (x1res, x2res) | Error e, _ -> Error e | _, Error e -> Error e // Next, define a builder with 'MergeSources' and 'BindReturn' type ResultBuilder() = member _.MergeSources(t1: Result<'T,'U>, t2: Result<'T1,'U>) = Result.zip t1 t2 member _.BindReturn(x: Result<'T,'U>, f) = Result.map f x let result = ResultBuilder() let run r1 r2 r3 = // And here is our applicative! let res1: Result<int, string> = result { let! a = r1 and! b = r2 and! c = r3 return a + b - c } match res1 with | Ok x -> printfn "%s is: %d" (nameof res1) x | Error e -> printfn "%s is: %s" (nameof res1) e let printApplicatives () = let r1 = Ok 2 let r2 = Ok 3 // Error "fail!" let r3 = Ok 4 run r1 r2 r3 run r1 (Error "failure!") r3Repro steps
Please provide the steps required to reproduce the problem
let runValidations v1 v2 v3 = let val1 = validation { let! a = v1 and! b = v2 and! c = v3 return a + b - c } match val1 with | Success s -> printfn "%A is: %A" (nameof val1) s | Failure f -> printfn "%A is: %A" (nameof val1) f let printValidations () = let r1 = Validation<string list, int32>.Success 2 let r2 = Validation<string list, int32>.Success 3 let r3 = Validation<string list, int32>.Success 4 runValidations r1 r2 r3 runValidations r1 (Validation<string list, int32>.Failure [ "Meow 1" ]) (Validation<string list, int32>.Failure [ "Meow 2" ]) [<EntryPoint>] let main _ = printValidations() 0- Step B
Expected behavior
validation CE builder should be defined and the output of the program should be:
"val1" is: 1 "val1" is: ["Meow 1"; "Meow 2"]Actual behavior
The value or constructor 'validation' is not defined.Known workarounds
open FSharpPlus.Data module Result = let zip r1 r2 = match r1, r2 with | Ok o1, Ok o2 -> Ok (o1, o2) | Error e1, _ -> Error e1 | _, Error e2 -> Error e2 // Next, define a builder with 'MergeSources' and 'BindReturn' type ResultBuilder() = member _.MergeSources(t1: Result<'T,'U>, t2: Result<'T1,'U>) = Result.zip t1 t2 member _.BindReturn(x: Result<'T,'U>, f) = Result.map f x module Validation = let zip x1 x2 = match (x1, x2) with | Success s1, Success s2 -> Success (s1, s2) | Failure f1, Success _ -> Failure f1 | Success _, Failure f2 -> Failure f2 | Failure f1, Failure f2 -> Failure (f1 @ f2) type ValidationBuilder() = member _.MergeSources(t1, t2) = Validation.zip t1 t2 member _.BindReturn(x, f) = Validation.map f x member _.Bind(x, f) = Validation.bind f x let result = ResultBuilder() let validation = ValidationBuilder() let runResults r1 r2 r3 = // And here is our applicative! let res1: Result<int, string> = result { let! a = r1 and! b = r2 and! c = r3 return a + b - c } match res1 with | Ok o -> printfn "%A is: %A" (nameof res1) o | Error e -> printfn "%A is: %A" (nameof res1) e let runValidations v1 v2 v3 = let val1 = validation { let! a = v1 and! b = v2 and! c = v3 return a + b - c } match val1 with | Success s -> printfn "%A is: %A" (nameof val1) s | Failure f -> printfn "%A is: %A" (nameof val1) f let printResults () = let r1 = Ok 2 let r2 = Ok 3 let r3 = Ok 4 runResults r1 r2 r3 runResults r1 (Error "failure!") r3 let printValidations () = let r1 = Validation<string list, int32>.Success 2 let r2 = Validation<string list, int32>.Success 3 let r3 = Validation<string list, int32>.Success 4 runValidations r1 r2 r3 runValidations r1 (Validation<string list, int32>.Failure [ "Meow 1" ]) (Validation<string list, int32>.Failure [ "Meow 2" ]) [<EntryPoint>] let main _ = printResults() printValidations() 0Output:
"res1" is: 1 "res1" is: "failure!" "val1" is: 1 "val1" is: ["Meow 1"; "Meow 2"]Related information
- Operating system: Windows 10 professional
- Branch:
master - .NET Runtime, CoreCLR or Mono Version: .NET 5.0 + F# 5.0 (lang preview enabled)
- Performance information, links to performance testing scripts
Metadata
Metadata
Assignees
Labels
No labels