DEV Community

Iven Marquardt
Iven Marquardt

Posted on

3

Turn non-algebraic, imperative arrays into a monad transformer

Turns out that although JS arrays are not algebraic, you can implement a transformer-like type ArrayT m a = m (Array (m a)). It behaves like a transformer & adheres to the monad laws for many m but there are no guarantees that this holds for all m:

// ARRAYT

const arrFoldT = chain => f => init => mmx =>
  chain(mmx) (mx => {
    const go = (acc, i) =>
      i === mx.length
        ? acc
        : chain(mx[i]) (x =>
            go(f(acc) (x), i + 1))

    return go(init, 0);
  });

const arrAppendT = ({chain, of}) => mmx => mmy =>
  arrFoldT(chain)
    (acc => x =>
      chain(acc) (acc_ =>
        of(arrSnoc(of(x)) (acc_)))) (mmx) (mmy);

const arrChainT = ({chain, of}) => mmx => fmm =>
  arrFoldT(chain)
    (acc => x =>
      arrAppendT({chain, of}) (acc) (fmm(x)))
        (of([]))
          (mmx);

const arrOfT = of => x => of([of(x)]);

// OPTION

const Option = union("Option");

const None = Option("None", {});

const Some = some => Option(Some, {some});

const optChain = mx => fm =>
  match(mx, {
    None: _ => None,
    Some: ({some: x}) => fm(x)
  });

const optOf = x => Some(x);

// OPTARR

const optArrChain = arrChainT({chain: optChain, of: optOf});

const optArrOf = arrOfT(optOf);

// MAIN

const mmw = Some([Some(1), Some(2), Some(3)]),
  mmx = Some([Some(1), None, Some(3)]),
  mmy = Some([Some(1), Some(0), Some(3)]),
  mmz = None;

const main = optArrChain(mmw) (x => optArrOf(x * x)),
  main2 = optArrChain(mmx) (x => optArrOf(x * x)),
  main3 = optArrChain(mmx) (x => x === 0 ? None : optArrOf(x * x)),
  main4 = optArrChain(mmz) (x => optArrOf(x * x));

main;  // Some([Some(1), Some(4), Some(9)])
main2; // None
main3; // None
main4; // None
Enter fullscreen mode Exit fullscreen mode

You can find a running example on repl.

Top comments (0)

Sentry image

See why 4M developers consider Sentry, “not bad.”

Fixing code doesn’t have to be the worst part of your day. Learn how Sentry can help.

Learn more

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay