fpEs


Functional Programming for EcmaScript(Javascript)
Why
Originally I would like to have some features of Optional & Rx-like & PubSub functions;
however somehow that's too heavy if including them at the same time.
Thus the implementation just includes the core functions, and more clear to use.
Special thanks:
Installation
Node.js
node >= 6.0
npm i fpes
Browser
bundled files for web/browser usages:
all
fp
maybe
monadio
pattern
publisher
Usage
Import
- You can include the entire library:
import fpEs from 'fpEs';
- There are 5 modules in this library, you can include them individually:
Just include things you need:
import {Maybe} from "fpEs";
var m = Maybe.just(1);
or
import {
compose, curry,
} from "fpEs";
or
import {
compose, curry,
} from "fpEs/fp";
Common FP (Compose, Curry)
Example:
import {
compose, curry,
} from "fpEs/fp";
console.log(compose((x)=>x-8, (x)=>x+10, (x)=>x*10)(4))
console.log(compose((x)=>x+2, (x,y)=>x*y)(4,10))
console.log(curry((x, y, z) => x + y + z)(1,2,3))
console.log(curry((x, y, z) => x + y + z)(1)(2,3))
console.log(curry((x, y, z) => x + y + z)(1,2)(3))
console.log(curry((x, y, z) => x + y + z)(1)(2)(3))
PatternMatching
Example:
import {
either,
inCaseOfObject, inCaseOfEqual, inCaseOfClass, otherwise,
SumType, ProductType, CompType,
TypeNumber,
TypeString,
TypeNaN,
TypeObject,
TypeArray,
TypeNull,
TypeEqualTo,
TypeClassOf,
TypeRegexMatches,
} from "fpEs/pattern";
console.log(either({}, inCaseOfObject((x)=>JSON.stringify(x)), otherwise((x)=>false)));
console.log(either([], inCaseOfObject((x)=>JSON.stringify(x)), otherwise((x)=>false)));
console.log(either(null, inCaseOfObject((x)=>JSON.stringify(x)), otherwise((x)=>false)));
console.log(either(undefined, inCaseOfObject((x)=>JSON.stringify(x)), otherwise((x)=>false)));
console.log(either("", inCaseOfObject((x)=>JSON.stringify(x)), otherwise((x)=>false)));
var err = undefined;
err = undefined;
either(1, inCaseOfEqual(1, (x)=>x+1)).should.equal(2);
(err === undefined).should.equal(true);
err = undefined;
try {
either(1, inCaseOfEqual(2, (x)=>x+1));
} catch (e) {
err = e;
}
(err === undefined).should.equal(false);
err = undefined;
try {
either(1, inCaseOfEqual(2, (x)=>x+1), otherwise((x)=>x+2)).should.equal(3);
} catch (e) {
err = e;
console.log(e);
}
(err === undefined).should.equal(true);
var s;
s = new SumType(new ProductType(TypeString, TypeNumber), new ProductType(TypeRegexMatches('c+')));
console.log(s.apply("1", "2asdf") === undefined);
console.log(s.apply("1", 2) === undefined);
console.log(s.apply("1") === undefined);
console.log(s.apply("ccc") === undefined);
Maybe (Sync)
Example:
import Maybe from "fpEs/maybe";
var m;
m = Maybe.just(1).map((x)=>x+2).map((x)=>x+3);
console.log(m.unwrap());
m = Maybe.just(1);
console.log(m.isPresent());
console.log(m.isNull());
m = Maybe.just(null);
console.log(m.isPresent());
console.log(m.isNull());
m = Maybe.just(undefined);
console.log(m.isPresent());
console.log(m.isNull());
m = Maybe.just(1);
console.log(m.or(3).unwrap());
console.log(m.or(4).unwrap());
m = Maybe.just(null);
console.log(m.or(3).unwrap());
console.log(m.or(4).unwrap());
m = Maybe.just(undefined);
console.log(m.or(3).unwrap());
console.log(m.or(4).unwrap());
m = Maybe.just(1);
v = 0;
m.letDo(function () {
v = 1;
});
console.log(v);
m = Maybe.just(null);
v = 0;
m.letDo(function () {
v = 1;
});
console.log(v);
m = Maybe.just(undefined);
v = 0;
m.letDo(function () {
v = 1;
});
console.log(v);
m = Maybe.just(0);
v = m.letDo(function (p) {
return p + 2
}).orDo(function () {
return 3
}).unwrap();
console.log(v);
m = Maybe.just(undefined);
v = m.letDo(function (p) {
return p + 2
}).orDo(function () {
return 3
}).unwrap();
console.log(v);
MonadIO/Rx.Observable (Async,Sync)
Example:
import Maybe from "fpEs/maybe";
import MonadIO from "fpEs/monadio";
var {promiseof, doM} = MonadIO;
var p = undefined;
var m = MonadIO.just(0);
var v = 0;
m = MonadIO.just(0);
v = 0;
m
.map((val)=>val+1)
.map((val)=>val+2)
.flatMap((val)=>MonadIO.just(val+1).map((val)=>val+1).map((val)=>val+1))
.subscribe((val)=>v=val);
console.log(v);
m = MonadIO.just(0);
v = 0;
p = m
.map((val)=>val+1)
.map((val)=>val+2)
.map((val)=>val+3)
.subscribe((val)=>v=val, true);
console.log(v);
p.then(function () {
console.log(v);
});
v = 0;
p = doM(function *() {
var value = yield promiseof(5);
var value2 = yield promiseof(11);
var value3 = yield Maybe.just(3);
var value4 = yield MonadIO.just(3);
return value + value2 + value3 + value4;
});
p.then((x)=>console.log(x));
Publisher(PubSub-like)
Example:
import Publisher from "fpEs/publisher";
var p = new Publisher();
var v = 0;
p = new Publisher();
v = 0;
p.subscribe((i)=>v=i);
p.publish(1);
console.log(v);
p = new Publisher();
v = 0;
p.subscribe((i)=>v=i);
p.publish(1, true);
console.log(v);
setTimeout(()=>{
console.log(v);
},100);
p = new Publisher();
v = 0;
p.map((x)=>x+2).map((x)=>x+3).subscribe((i)=>v=i);
p.publish(1, true);
console.log(v);
setTimeout(()=>{
console.log(v);
},100);
p = new Publisher();
v = 0;
var callback = (i)=>v=i;
p.subscribe(callback);
p.publish(1);
console.log(v);
v = 0;
p.unsubscribe(callback);
p.publish(1);
console.log(v);