3
votes

I am implementing the monad transformer of the Maybe (aka Option) type in Javascript (please note that I use type-dictionary passing):

const optOfT = of => x =>
  of(optOf(x));

const optMapT = map => f => ttx =>
  map(optMap(f)) (ttx);

const optApT = chain => ttf => ttx =>
  chain(tf =>
    chain(tx =>
      optAp(tf) (tx)) (ttx)) (ttf);

const optChainT = chain => fm => mmx =>
  chain(mx =>
    optChain(fm) (mx)) (mmx);

(map ~ <$>, ap ~ <*>, chain ~ =<<, of = pure/return)

While this code works I wonder if I can implement optApT without the monad constraint for the outer monad. I stumbled upon this Haskell example:

(<<**>>) :: (Applicative a, Applicative b) => a (b (s -> t)) -> a (b s) -> a (b t)
abf <<**>> abs = pure (<*>) <*> abf <*> abs

This seems exactly what I want, but I can't recognize the evaluation order of pure (<*>) <*> abf <*> abs and which <*> operator belongs to which applicative layer:

const optApT = (ap, of) => ttf => ttx =>
  ...?

Any hint is appreciated.

1

1 Answers

2
votes

Hopefully this helps...

Here are the types associated with the various type-class functions:

abf <<**>> abs = pure (<*>) <*> abf <*> abs
                  (4)  (3)  (2)     (1)

(1), (2): the `ap` for type a
(3): the `ap` for type b
(4): the `pure` for type a

And the evaluation order is:

(pure (<*>)) <*> abf <*> abs