-
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