I'm trying to derive function of three args, using simple function chaining.
The function should be of type
addToList :: a -> a -> a -> [a]
and be pointfree analogue of
addToList :: a b c = (a : (b : (c : [])))
So far, I've figured out
addToList = ((.)((.) (flip (:)) . (flip (:))) . (flip (:))) []
But it works in reverse:
Prelude> addToList 4 5 6
[6,5,4]
and looks bulky.
How can one get something nice like
(.) (.) (.) (:) (:) (: [])
that works as follows:
Prelude> addToList 4 5 6
[4,5,6]
?
Let's have a look at a more general version, that uses three functions f
, g
and h
:
func a b c = f a (g b (h c))
In our case, f = (:)
, g = (:)
and h = return
, but we can use this for any triple of functions that follow the same scheme:
func a b c = (f a . g b . h) c
For the next step, write the first application of (.)
in prefix form, so that it's easier to combine (.) (f a)
and the rest later:
func a b = (.) (f a) (g b . h)
= (.) (f a) (g b . h)
= (.) (f a) ((.) (g b) h)
= (.) (f a) (flip (.) h (g b))
= (.) (f a) ((flip (.) h . g) b)
= (.) (f a) . (flip (.) h . g) b
We can now do the same for a
:
func a = (.) (f a) . (flip (.) h . g)
= (.) ((.) (f a)) (flip (.) h . g)
= flip (.) (flip (.) h . g) ((.) (f a))
= flip (.) (flip (.) h . g) . (.) (f a)
= flip (.) (flip (.) h . g) . (.) . f a
Since flip (.) x
is (.x)
we can get rid of flip
:
func = flip (.) (flip (.) h . g) . (.) . f
= flip (.) ((.h) . g) . (.) . f
= (.((.h) . g)) . (.) . f
All we have to do now is to insert the definitions of f
, g
and h
:
func = (.((.return) . (:))) . (.) . (:)
I didn't check whether there is a shorter version, but since this is the same result as pointfree.io yields, it should be more or less optimal.
That being said, if you compare
addToList = (.((.return) . (:))) . (.) . (:)
with
addToList a b c = [a, b, c]
which one would you like to read in three months?