Free

data. Free

new Free()

The Free union type can be used to transform any structure into a monad. This means, Free can be used to create DSLs or custom interpreters for actions.

Version:
  • 3.0.0
Source:
Example
const {Free} = require('futils').data;
const {Cont, Return} = Free;

Free.Cont(1, Free.Return); // -> Cont(1)
Cont(1, Return);           // -> Cont(1)

Free.Return(1);            // -> Return(1)
Return(1);                 // -> Return(1)

Methods

(static) from(F) → {Cont}

A shortcut version of Free.liftM, takes a constructor function and returns a lifted function which puts the resulting structure into a Free.Cont

Source:
Parameters:
Name Type Description
F function

The constructor function to lift

Returns:
Type:
Cont

A Free.Cont instance

Example
const {UnionType} = require('futils').adt;
const {Free} = require('futils').data;
const {compose} = require('futils').lambda;

const Num = UnionType('Num', {Int: ['value'], Float: ['value']});
const {Int, Float} = Num;

const asInt = compose(Free.from(Int), parseInt);
const asFloat = compose(Free.from(Float), parseFloat);

const prog = asInt(100.25).map(n => n.toFixed(2)).flatMap(asFloat);

(static) liftM(a) → {Cont}

Lifts a structure into a Free.Cont

Source:
Parameters:
Name Type Description
a any

The structure

Returns:
Type:
Cont

A Free.Cont instance

Example
const {UnionType} = require('futils').adt;
const {Free} = require('futils').data;

const Num = UnionType('Num', {Int: ['value'], Float: ['value']});
const {Int, Float} = Num;

const asInt = n => Free.liftM(Int(parseInt(n, 10)));
const asFloat = n => Free.liftM(Float(parseFloat(n)));

const prog = asInt(100.25).map(n => n.toFixed(2)).flatMap(asFloat);

(static) of(a) → {Return}

Lifts a value into a Free.Return

Source:
Parameters:
Name Type Description
a any

The value to lift

Returns:
Type:
Return

A Free.Return instance

Example
const {Free} = require('futils').data;

Free.of(1); // -> Return(1)

ap(a) → {Return|Cont}

Free applicative implementation, applies a function in a Free to a value in another Free

Source:
Parameters:
Name Type Description
a Return | Cont

The Free that holds the value

Returns:
Type:
Return | Cont

Free which returns the result of applying the function

Example
const {Free} = require('futils').data;

Free.of(n => n + 1).ap(Free.of(1)); // -> Return(2)

flatMap(f) → {Return|Cont}

Maps a Free returning function over a Free.Return or Free.Cont and flattens the result

Source:
Parameters:
Name Type Description
f function

A Free returning function to map

Returns:
Type:
Return | Cont

A new Free

Example
const {Free} = require('futils').data;

Free.of(1).flatMap(n => Free.of(n + 1)); // -> Return(2)

interpret(transform, A) → {ApplicativeMonad}

If given a interpreter function, which should be a natural transformation, interprets the computation build with Free. This method is aliased to traverse.

Source:
Parameters:
Name Type Description
transform function

The interpreter function

A ApplicativeMonad

The data structure to interpret into

Returns:
Type:
ApplicativeMonad

A data structure which holds the result

Example
const {UnionType} = require('futils').adt;
const {Free, Id} = require('futils').data;

const Num = UnionType('Num', {Int: ['value'], Float: ['value']});
const {Int, Float} = Num;

const cmp = (f, g) => x => f(g(x));

const asInt = cmp(Free.from(Int), parseInt);
const asFloat = cmp(Free.from(Float), parseFloat);

const prog = asInt(100.25).map(n => n.toFixed(2)).flatMap(asFloat);

const nt = num => num.caseOf({
    Int: n => isNaN(n) ? Id.of(0) : Id.of(Math.round(n)),
    Float: n => isNaN(n) ? Id.of(0) : Id.of(n)
});

prog.interpret(nt, Id); // -> Id(100.00)

// or: prog.traverse(nt, Id); // -> Id(100.00)

map(f) → {Return|Cont}

Maps a function over a Free.Return or a Free.Cont and returns a new Free

Source:
Parameters:
Name Type Description
f function

The function to map

Returns:
Type:
Return | Cont

A new Free

Example
const {Free} = require('futils').data;

Free.of(1).map(n => n + 1); // -> Return(2)