functional-validation

The validation monad

Functional Validation

Fantasy Land Compliant!

Indigenous Complaint!

This is an implementation of the Validation monad from Haskell and from the Scalaz library. It is also naturally a functor, applictive and monoid.

Just like in scalaz, theres lots of fuss about if this is a true monad and monoid. The interfaces remain true but not all laws like the associativity law for monoid append hold true.

Monoid error concatenation:

var Success = require("funtional-validation/success");
var Failure = require("funtional-validation/failure");
 
var id = function(n) { return n; };
 
var success1 = new Success(1);
var success2 = new Success(2);
var failure1 = new Failure(["error1"]);
var failure2 = new Failure(["error2"]);
 
var combo1 = success1.concat(success2);
console.log("Value: " + combo1.fold(id, id));
// prints "Value: 1" 
 
var combo2 = success1.concat(error1);
console.log("Value: " + JSON.stringify(combo2.fold(id, id)));
// prints "Value: ['error1']" 
 
var combo3 = failure1.concat(failure2);
console.log("Value: " + JSON.stringify(combo2.fold(id, id)));
//prints "Value: ['error1', 'error2']" 

Functor composition:

var Success = require("funtional-validation/success");
var Failure = require("funtional-validation/failure");
 
var id = function(n) { return n; };
 
var success = new Success(1);
var failure = new Failure(["error"]);
 
var map1 = success.map(function(n) { return n + 1; });
console.log("Value: " + map1.fold(id, id));
//prints "Value: 2" 
 
var map2 = failure.map(function(n) { return "fail"; });
console.log("Value: " + JSON.stringify(map1.fold(id, id)));
//prints "Value: ['error']" 

Applicative composition:

var Validation = require("funtional-validation");
var Success    = require("funtional-validation/success");
var Failure    = require("funtional-validation/failure");
var curry      = require("lodash").curry;
 
var id = function(n) { return n; };
 
var successString  = new Success("beep");
var successNumber  = new Success(1);
var successBoolean = new Success(true);
 
var failure1 = new Failure(["error1"]);
var failure2 = new Failure(["error2"]);
 
var lifted = Validation.of(curry(function(abc) {
    return a + " - " + b + " - " + c;
}));
 
var applied = lifted.ap(successString).ap(successNumber).ap(successBoolean);
console.log("Value: " + applied.fold(id, id));
//prints "Value: beep - 1 - true" 
 
var errored = lifted.ap(failure1).ap(successString).ap(failure2);
consosle.log("Value: " + JSON.stringify(errored.fold(id, id)));
//prints "Value: ['error1', 'error2']" 

Monadic composition (flatMap is an alias for chain):

var Success = require("funtional-validation/success");
var Failure = require("funtional-validation/failure");
 
var success = new Success(1);
var failure = new Failure(["error"]);
 
var applied = success.flatMap(function(n) {
    return new Success(+ 1);
});
console.log("Value: " + applied.fold(id, id));
//prints "Value: 2" 
 
var ignored = failure.flatMap(function(n) {
    return new Success(+ 1);
});
console.log("Value: " + JSON.stringify(applied.fold(id, id)));
//prints "Value: ['error']"