I'd like to share a little Haskell snippet (I wanted to say "idiom" but actually I'm not sure if I've seen it used anywhere else...) that I quite like:
join (,) 9
What does this do? On its own, not much - in fact you just get:
(9,9)
...which you'd have been much better off typing in yourself. Where it can come-in handy though is when writing code in a pointfree style if you have a need to duplicate an anonymous value into both parts of a pair:
functionWhichTakesAPair . join (,) . functionWhichProducesASingleValue
Anyway, how / why does this construct work....?
The
(,) is just the standard data constructor for a 2-tuple, a pair. (This constructor has type
a -> b -> (a,b) so you can always write
(,) 9 9 as an alternative notation for
(9,9) if you wish).
The
join is the standard function
:: Monad m => m (m a) -> m a we know from monadic programming (Control.Monad). But this just raises the question of how it can make sense to apply it to
(,) which as we've seen is a function of type
a -> b -> (a,b).
The answer is of course that this function may be considered to be of type
m (m a). This is because
Control.Monad.Instances declares any partially applied function (eg
a -> ...) to be a monad (the type
a can be seen as representing an encapsulated environment which is threaded through by the monadic bind). This then means that a function of two arguments (such as
(,)) can be seen as having type
m (m a) which is just what we need to be able to apply
join. The net result is that the single argument of the resulting function (
join (,)) is passed in twice as desired.
This of course generalises to functions other than
(,) - whenever we use
join f where
f is a function of two arguments, we end up with a function of one argument which is passed into
f twice.