I am working through the 20 Intermediate Haskell Exercises at the moment, which is quite a fun exercise. It involves implementing various instances of the typeclasses Functor
and Monad
(and functions that takes Functor
s and Monad
s as arguments) but with cute names like Furry
and Misty
to disguise what we're doing (makes for some interesting code).
I've been trying to do some of this in a point-free style, and I wondered if there's a general scheme for turning a point-ful (?) definition into a point-free definition. For example, here is the typeclass for Misty
:
class Misty m where
unicorn :: a -> m a
banana :: (a -> m b) -> m a -> m b
(the functions unicorn
and banana
are return
and >>=
, in case it's not obvious) and here's my implementation of apple
(equivalent to flip ap
):
apple :: (Misty m) => m a -> m (a -> b) -> m b
apple x f = banana (\g -> banana (unicorn . g) x) f
Later parts of the exercises have you implement versions of liftM
, liftM2
etc. Here are my solutions:
appleTurnover :: (Misty m) => m (a -> b) -> m a -> m b
appleTurnover = flip apple
banana1 :: (Misty m) => (a -> b) -> m a -> m b
banana1 = appleTurnover . unicorn
banana2 :: (Misty m) => (a -> b -> c) -> m a -> m b -> m c
banana2 f = appleTurnover . banana1 f
banana3 :: (Misty m) => (a -> b -> c -> d) -> m a -> m b -> m c -> m d
banana3 f x = appleTurnover . banana2 f x
banana4 :: (Misty m) => (a -> b -> c -> d -> e) -> m a -> m b -> m c -> m d -> m e
banana4 f x y = appleTurnover . banana3 f x y
Now, banana1
(equivalent to liftM
or fmap
) I was able to implement in pointfree style, by a suitable definition of appleTurnover
. But with the other three functions I've had to use parameters.
My question is: is there a recipe for turning definitions like these into point-free definitions?