Skip to content

Instantly share code, notes, and snippets.

@Porges
Created April 15, 2015 01:46
Show Gist options
  • Save Porges/dcb4083efb34019685d7 to your computer and use it in GitHub Desktop.
Save Porges/dcb4083efb34019685d7 to your computer and use it in GitHub Desktop.
// 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