[SOLVED] In Haskell how to "apply" functions in nested context to a value in context?

Issue

nestedApply :: (Applicative f, Applicative g) => g (f (a -> b)) -> f a -> g (f b)

As the type indicates, how to get that (a->b) applied to that a in the context f?

Thanks for help.

Solution

With

nestedApply :: (Applicative f, Applicative g) 
            => g (f (a -> b))  
            ->    f  a 
            -> g (f       b )

to get that (a->b) applied to that a in the context f, we need to operate in the context g.

And that’s just fmap.

It’s clearer with the flipped signature, focusing on its last part

flip nestedApply :: (Applicative f, Applicative g) 
            =>    f  a 
            -> g (f (a -> b))     --- from here
            -> g (f       b )     --- to here

So what we have here is

nestedApply gffun fx = fmap (bar fx) gffun

with bar fx being applied under the g wraps by fmap for us. Which is

bar fx ::         f (a -> b)
            ->    f       b   

i.e.

bar ::            f  a
            ->    f (a -> b)
            ->    f       b   

and this is just <*> isn’t it, again flipped. Thus we get the answer,

nestedApply gffun fx  =  fmap (<*> fx) gffun

As we can see only fmap capabilities of g are used, so we only need

nestedApply :: (Applicative f, Functor g) => ...

in the type signature.


It’s easy when writing it on a sheet of paper, in 2D. Which we imitate here with the wild indentation to get that vertical alignment.

Yes we the humans learned to write first, on paper, and to type on a typewriter, much later. The last generation or two were forced into linear typing by the contemporary devices since the young age but now the scribbling and talking (and gesturing and pointing) will hopefully be taking over yet again. Inventive input modes will eventually include 3D workflows and that will be a definite advancement. 1D bad, 2D good, 3D even better. For instance many category theory diagrams are much easier to follow (and at least imagine) when drawn in 3D. The rule of thumb is, it should be easy, not hard. If it’s too busy, it probably needs another dimension.

Just playing connect the wires under the wraps. A few self-evident diagrams, and it’s done.


Here’s some type mandalas for you (again, flipped):

-- <$>               -- <*>               -- =<<
f     a              f     a              f     a       
     (a -> b)        f    (a -> b)             (a -> f b)
f          b         f          b         f    (     f b)   -- fmapped, and
                                          f            b    -- joined

and of course the mother of all applications,

--      $
      a
      a -> b
           b

a.k.a. Modus Ponens (yes, also flipped).

Answered By – Will Ness

Answer Checked By – Marilyn (BugsFixing Volunteer)

Leave a Reply

Your email address will not be published.