Skip to content

Repository files navigation

fpEs

npm downloadnpm versionCI

licensestarsforks

Functional Programming for EcmaScript(Javascript)

Documentation: see docs/OVERVIEW.md for the module map, non-obvious behaviors, and a scenarios cookbook, and docs/API.md for the full export reference. The README below only covers a small subset of the API.

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 >= 8.3.0

  • Installation:
npm i fpes

Browser

bundled files for web/browser usages:

all


fp

maybe

monadio

pattern

publisher

Usage

Import

In the browser bundle, the global name is fpEs (see webpack library setting). In Node/npm, install and import the package as fpes (all lowercase).

  • You can include the entire library:
importfpEsfrom'fpes';
  • There are 5 modules in this library, you can include them individually:
    • Facades:
      • maybe
      • monadio
      • publisher
    • FP functions:
      • fp
      • pattern

Just include things you need:

import{Maybe}from"fpes";// or this one:/*import Maybe from "fpes/maybe";*/varm=Maybe.just(1);// It works

or

import{compose,curry,}from"fpes";

or

import{compose,curry,}from"fpes/fp";

Common FP (Compose, Curry)

Example:

import{compose,curry,}from"fpes/fp";// composeconsole.log(compose((x)=>x-8,(x)=>x+10,(x)=>x*10)(4))// 42console.log(compose((x)=>x+2,(x,y)=>x*y)(4,10))// 42// curryconsole.log(curry((x,y,z)=>x+y+z)(1,2,3))// 6console.log(curry((x,y,z)=>x+y+z)(1)(2,3))// 6console.log(curry((x,y,z)=>x+y+z)(1,2)(3))// 6console.log(curry((x,y,z)=>x+y+z)(1)(2)(3))// 6

PatternMatching

Example:

import{either,inCaseOfObject,inCaseOfEqual,inCaseOfClass,otherwise,SumType,ProductType,CompType,TypeNumber,TypeString,TypeNaN,TypeObject,TypeArray,TypeNull,TypeEqualTo,TypeClassOf,TypeRegexMatches,}from"fpes/pattern";// PatternMatchingconsole.log(either({},inCaseOfObject((x)=>JSON.stringify(x)),otherwise((x)=>false)));// "{}"console.log(either([],inCaseOfObject((x)=>JSON.stringify(x)),otherwise((x)=>false)));// falseconsole.log(either(null,inCaseOfObject((x)=>JSON.stringify(x)),otherwise((x)=>false)));// falseconsole.log(either(undefined,inCaseOfObject((x)=>JSON.stringify(x)),otherwise((x)=>false)));// falseconsole.log(either("",inCaseOfObject((x)=>JSON.stringify(x)),otherwise((x)=>false)));// false// otherwisevarerr=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);// SumTypevars;s=newSumType(newProductType(TypeString,TypeNumber),newProductType(TypeRegexMatches('c+')));console.log(s.apply("1","2asdf")===undefined);// trueconsole.log(s.apply("1",2)===undefined);// falseconsole.log(s.apply("1")===undefined);// trueconsole.log(s.apply("ccc")===undefined);// false

Maybe (Sync)

Example:

importMaybefrom"fpes/maybe";varm;// map (sync)m=Maybe.just(1).map((x)=>x+2).map((x)=>x+3);console.log(m.unwrap());// 6// isPresent/isNullm=Maybe.just(1);console.log(m.isPresent());// trueconsole.log(m.isNull());// falsem=Maybe.just(null);console.log(m.isPresent());// falseconsole.log(m.isNull());// truem=Maybe.just(undefined);console.log(m.isPresent());// falseconsole.log(m.isNull());// true// Orm=Maybe.just(1);console.log(m.or(3).unwrap());// 1console.log(m.or(4).unwrap());// 1m=Maybe.just(null);console.log(m.or(3).unwrap());// 3console.log(m.or(4).unwrap());// 4m=Maybe.just(undefined);console.log(m.or(3).unwrap());// 3console.log(m.or(4).unwrap());// 4// letDom=Maybe.just(1);v=0;m.letDo(function(){v=1;});console.log(v);// 1m=Maybe.just(null);v=0;m.letDo(function(){v=1;});console.log(v);// 0m=Maybe.just(undefined);v=0;m.letDo(function(){v=1;});console.log(v);// 0// letDo & orDom=Maybe.just(0);v=m.letDo(function(p){returnp+2}).orDo(function(){return3}).unwrap();console.log(v);// 2m=Maybe.just(undefined);v=m.letDo(function(p){returnp+2}).orDo(function(){return3}).unwrap();console.log(v);// 3

MonadIO/Rx.Observable (Async,Sync)

Example:

importMaybefrom"fpes/maybe";importMonadIOfrom"fpes/monadio";var{promiseof, doM}=MonadIO;varp=undefined;varm=MonadIO.just(0);varv=0;// syncm=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);// 6// asyncm=MonadIO.just(0);v=0;p=m.map((val)=>val+1).map((val)=>val+2).map((val)=>val+3).subscribe((val)=>v=val,true);// Async: trueconsole.log(v);// 0p.then(function(){console.log(v);// 6});// DoNotationv=0;p=doM(function*(){varvalue=yieldpromiseof(5);varvalue2=yieldpromiseof(11);varvalue3=yieldMaybe.just(3);varvalue4=yieldMonadIO.just(3);returnvalue+value2+value3+value4;});p.then((x)=>console.log(x));// 22

Publisher(PubSub-like)

Example:

importPublisherfrom"fpes/publisher";varp=newPublisher();varv=0;// syncp=newPublisher();v=0;p.subscribe((i)=>v=i);p.publish(1);console.log(v);// 1// asyncp=newPublisher();v=0;p.subscribe((i)=>v=i);p.publish(1,true);// Async: trueconsole.log(v);// 0setTimeout(()=>{console.log(v);// 1},100);// mapp=newPublisher();v=0;p.map((x)=>x+2).map((x)=>x+3).subscribe((i)=>v=i);p.publish(1,true);console.log(v);// 0setTimeout(()=>{console.log(v);// 6},100);// unsubscribep=newPublisher();v=0;varcallback=(i)=>v=i;p.subscribe(callback);p.publish(1);console.log(v);// 1v=0;p.unsubscribe(callback);p.publish(1);console.log(v);// 0

Development

Prerequisites

  • Node ^22.18.0 || >=24.11.0 (required by Babel 8 dev toolchain)
  • Consumer runtime: >= 8.3.0 (see engines in package.json)

Release Checklist

  1. npm run release:check — run tests, run the prepare build through npm pack, and verify tarball contents
  2. Inspect the npm pack --dry-run --json file list (no test/config leak; docs links included)
  3. git tag -a v<version> -m "Release <version>" — create version tag at the final release commit
  4. npm login — authenticate to npm
  5. npm publish (add --otp=<code> if 2FA enabled)
  6. git push origin master — push the release commit explicitly
  7. git push origin v<version> — push only the release tag explicitly
  8. Verify unpkg: https://unpkg.com/fpes@<version>/dist/bundle.min.js