Created
April 15, 2015 01:46
-
-
Save Porges/dcb4083efb34019685d7 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// First, the validation type (applicative only): | |
type Validation<'e, 't> = | |
| ErrorCollection of 'e list | |
| Validated of 't | |
let (<*>) (f : Validation<'e, 'a -> 'b>) (v : Validation<'e, 'a>) : Validation<'e, 'b> = | |
match f, v with | |
| ErrorCollection e1, ErrorCollection e2 -> ErrorCollection (List.append e1 e2) | |
| ErrorCollection e1, _ -> ErrorCollection e1 | |
| _, ErrorCollection e2 -> ErrorCollection e2 | |
| Validated f, Validated v -> Validated (f v) | |
let validationError e = ErrorCollection [e] | |
let valid x = Validated x | |
let validate f v = Validated f <*> v | |
let (<^>) = validate // dubious :) | |
// Next, the either-like type (monadic): | |
type Result<'e, 't> = // todo: write a short-circuiting computation expression for this | |
| Failure of 'e | |
| Success of 't | |
// Can convert from validation to result: | |
let fromValidation = function | |
| ErrorCollection e -> Failure e | |
| Validated v -> Success v | |
// Some example functions: | |
type ValidationErrors = BadServer | BadAddress | |
let getServer input : Validation<ValidationErrors, string> = validationError BadServer | |
let getAddress input : Validation<ValidationErrors, string> = validationError BadAddress | |
type ServerAndAddress = { server: string ; address: string } | |
let getServerAndAddress input = (fun s a -> {server = s ; address = a}) <^> (getServer input) <*> (getAddress input) | |
// With hypothetical computation expression: | |
////let myFunc input = result { | |
//// // can write it inline: | |
//// let! (server, address) = (fun s a -> s, a) <^> (getServer input) <*> (getAddress input) |> fromValidation | |
//// | |
//// // or: | |
//// let! serverAndAddress = fromValidation (getServerAndAddress input) | |
//// | |
//// return true | |
//// } | |
[<EntryPoint>] | |
let main argv = | |
match getServerAndAddress () with | |
| ErrorCollection errs -> printfn "Failed: %A" errs | |
| Validated v -> printfn "Success: %A" v | |
0 // return an integer exit code |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment