functional-validation

The validation monad

npm install functional-validation
17 downloads in the last week
53 downloads in the last month

Functional Validation

Build Status

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.

Examples

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(a, b, c) {
    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(n + 1);
});
console.log("Value: " + applied.fold(id, id));
//prints "Value: 2"

var ignored = failure.flatMap(function(n) {
    return new Success(n + 1);
});
console.log("Value: " + JSON.stringify(applied.fold(id, id)));
//prints "Value: ['error']"
npm loves you