JSFiddle - React, Tailwind, and code Playground

by dimitrs_papadimitriou

JavaScript

var Coyoneda = (x, g) => ({
  N: "Coyoneda",
  map: f => Coyoneda(x, x => f(g(x))),
  chain: f => f(g(x)),
  run: () => g(x),
  cata: alg => alg(g(x))
});

var liftC = x => Coyoneda(x, y => y);

var t = liftC({ v: 1 }).chain(x => liftC({ v: 1 + x.v }));
console.log(t.run());
var IO = fn => ({
  N: "IO",
  map: f => IO(() => f(fn())),
  chain: f => IO(() => f(fn()).run()),
  run: () => fn(),
  fold: (acc, accf) => accf(acc, fn()),
  cata: alg => alg(fn())
});
var Id = v => ({
  N: "Id",
  v: v,
  map: f => Id(f(v)),
  chain: f => f(v),
  cata: alg => alg(v)
});

var PureF = x => ({
  N: "PureF",
  x: x,
  map: g => PureF(g(x)),
  chain: g => g(x),
  fold: (acc, accf) => accf(acc, x),
  cata: alg => alg(x),
  foldMap: (interpreter, typeRep) => {
    return typeRep(x)
  }
});

var FreeF = fx => ({
  N: "FreeF",
  fx: fx,
  map: g => FreeF(fx.map(x => x.map(g))),
  chain: g => FreeF(fx.map(x => x.chain(g))),
  cata: alg => fx.map(x => x.cata(alg)),
  fold: (acc, accf) =>
    accf(
      accf(acc, fx.map(i => i.fold(acc, accf)).fold(acc, accf)),
      fx.fold(acc, accf)
    ),

  foldMap: (interpreter, typeRep) => {
    return fx.map(i =>
      i
        .evaluate(interpreter)
        .chain(result => i(result).foldMap(interpreter, typeRep))
    );  
  }
});

var toIO = x => liftC(x); //liftC(x) // IO(() => x);
var liftF = command => FreeF(toIO(command).map(PureF));

var e = liftF({ v: 4 }).chain(t => liftF({ v: t + 4 }));
//console.log(e)
console.log(
  FreeF(toIO(PureF({ v: 4 }))).chain(z => FreeF(toIO(PureF({ v: 4 + z.v }))))
);
console.log(
  FreeF(toIO(PureF({ v: 4 }))).chain(z => FreeF(toIO(PureF({ v: 4 + z.v }))))
);

toIO = x => liftC(x);

var t = FreeF(toIO(PureF({ v: 4 }))).chain(z =>
  FreeF(toIO(PureF({ v: 4 + z.v })))
);

var set = number =>
  liftF({
    evaluate: interpreter => interpreter.set(number)
  });

var get = liftF({
  evaluate: interpreter =>
    interpreter.get({
      v: 5
    })
});

var interpreter = {
  get: o => toIO(o.v),
  set: o =>...