Search code examples
javascripthaskellmonad-transformersapplicative

MaybeT applicative instance without monad constraint for the outer monad


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.


Solution

  • 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