I read Conor McBride and Ross Paterson "Functional Pearl / Idioms: Applied Programming with Effects:" ( new version with "idioms" in the title). I have a little difficulty with exercise 4, as explained below. Any hints would be much appreciated (especially: should I start writing fmap and join or return and >>= ?).
Problem Statement
You want to create instance Monad [] , where
return x = repeat x
and ap = zapp .
Standard library functions
As on page 2, ap applies the monadic value of the function to the monadic value.
ap :: Monad m => m (s -> t) -> ms -> mt ap mf ms = do f <- mf s <- ms return (fs)
I expanded it in canonical notation,
ap mf ms = mf >>= (\f -> (ms >>= \s -> return (fs)))
The list function zapp ("zippy application") applies a function from one list to the corresponding value in another, namely
zapp (f:fs) (s:ss) = fs : zapp fs ss
My difficulties
Please note that in expanded form mf :: m (a -> b) is a list of functions [(a -> b)] in our case. So, in the first application >>= we have
(f:fs) >>= mu
where mu = (\f -> (ms >>= \s -> return (fs))) . Now we can call fs >>= mu as a subroutine, but it does not know to remove the first ms element. (recall that we want the resulting list to be [f1 s1, f2 s2, ...]. I tried to hack something, but ... as predicted, this did not work ... any help would be greatly appreciated .
Thanks in advance!
Change 1
I think I got him to work; I first rewrote ap with fmap and join , as the user "comonad" suggested.
My leap of faith assumed fmap = map . If anyone can explain how to get there, I would really appreciate it. After this, it is clear that join works in the list of lists that the user "comonad" suggested, and should be a diagonal, \x -> zipWith ((!!) . unL) x [0..] . My full code is:
newtype L a = L [a] deriving (Eq, Show, Ord) unL (L lst) = lst liftL :: ([a] -> [b]) -> L a -> L b liftL f = L . f . unL joinL :: L (L a) -> L a joinL = liftL $ \x -> zipWith ((!!) . unL) x [0..] instance Functor L where fmap f = liftL (map f) instance Monad L where return x = L $ repeat x m >>= g = joinL (fmap gm)
I hope this is correct (it seems the βsolutionβ on page 18 of the article) ... thanks for the help, everyone!