I've been trying to make a combinator with this type signature:
(a -> b -> c) -> (c -> d -> e) -> a -> b -> d -> e
I've been through Data.Aviary.Birds and all the tacit programming help sites that I can find, but to no avail. Also, if there's a general algorithm to make these, it would be greatly appreciated but not necessary.
Our definition will start like this:
Now let's fill in the missing bits.
We need an
e; the only way to get that is by applying the second function to acandd.We are already given a
d, but we need ac. How do we get ac? By applying the first function to anaand ab.We are given both of these, so we're done.
We might stop here. This is a perfectly good definition.
But if we want to try to make it more terse, let's start by substituting the definition of
eand then of
cWe immediately see that we can eta reduce to remove the
d.The type is now slightly more general.
d -> ehas collapsed into one type variable, since it can actually be anything.We can now see in the aviary that our combinator is actually the blackbird, flipped.
And indeed if we look at the source for the blackbird, it looks much like what we have written.
Can we go more point-free? We might consider uncurrying
abcrewriting this nesting with function composition
and currying back again
And now we can chop off two more parameters.
We should definitely stop here. But what if we now flip the arguments
rewrite the right half to make it point-free
and eta reduce once more
and take one final ridiculous step
We are now point-free!