When I don’t grasp how an expression in Haskell works I often find it helps to decompose it into a more basic form.
Using the following definitions
sequenceA :: (Applicative f) => [f a] -> f [a]
sequenceA [] = pure []
sequenceA (x:xs) = (:) <$> x <*> sequenceA xs
instance Applicative ((->) r) where
pure x = (\_ -> x)
f <*> g = \x -> f x (g x)
I rewrote sequenceA [(+3),(+2)] 3 as
(\_ -> (:)) <*> (+3) <*> ((\_ -> (:)) <*> (+2) <*> (\_-> [])) $ 3
And then turned it into (please excuse the format; I’m not sure what the convention is for splitting lines)
(\d ->(\c->(\b -> (\a -> (\_ -> (:)) a (+3) a) b (\_ -> (:)) b) c (+2) c) d (\_ -> []) d) 3
This seems right when I work through it by hand, but I can’t get GHCi to accept it. What have I done wrong here? My second question is how to convert from this form into functional composition. I’ve tried substituing dots in various combinations, but GHCi rejects all of them….
Being an idle goodfornothing, I thought I would make a computer do the expansion for me. So into GHCi, I typed
So now I have funny versions of
pureand<*>which map strings which look like expressions to string which look like more complicated expressions. I then defined, similarly, the analogue ofsequenceA, replacing functions by strings.I was then able to generate the expanded form of the example as follows
which duly printed
This last, copied to the prompt, yielded
Comparing the output from my “metaprogram” with the attempt in the question shows a shorter initial prefix of lambdas, arising from a shallower nesting of
<*>operations. Remember, it’sso the outer
(:)should be only three lambdas deep. I suspect the proposed expansion may correspond to a differently bracketed version of the above, perhapsIndeed, when I evaluate
I get
which looks like it matches the (updated)
I hope this machine-assisted investigation helps to clarify what’s going on.