Search code examples
haskellcoding-stylepointfree

Trick for "reusing" arguments in Haskell?


From time to time I stumble over the problem that I want to express "please use the last argument twice", e.g. in order to write pointfree style or to avoid a lambda. E.g.

sqr x = x * x

could be written as

sqr = doubleArgs (*) where
   doubleArgs f x = f x x

Or consider this slightly more complicated function (taken from this question):

ins x xs = zipWith (\ a b -> a ++ (x:b)) (inits xs) (tails xs)

I could write this code pointfree if there were a function like this:

ins x = dup (zipWith (\ a b -> a ++ (x:b))) inits tails where
     dup f f1 f2 x = f (f1 x) (f2 x)

But as I can't find something like doubleArgs or dup in Hoogle, so I guess that I might miss a trick or idiom here.


Solution

  • From Control.Monad:

    join :: (Monad m) -> m (m a) -> m a
    join m = m >>= id
    
    instance Monad ((->) r) where
        return = const
        m >>= f = \x -> f (m x) x
    

    Expanding:

    join :: (a -> a -> b) -> (a -> b)
    join f = f >>= id
           = \x -> id (f x) x
           = \x -> f x x
    

    So, yeah, Control.Monad.join.

    Oh, and for your pointfree example, have you tried using applicative notation (from Control.Applicative):

    ins x = zipWith (\a b -> a ++ (x:b)) <$> inits <*> tails
    

    (I also don't know why people are so fond of a ++ (x:b) instead of a ++ [x] ++ b... it's not faster -- the inliner will take care of it -- and the latter is so much more symmetrical! Oh well)