For all the haskell fans out there:

I dunno, that function is still kinda Evil™. It’s one of those things where defining a function like that really gives zero benefit because it’s much clearer, and barely any wordier to just type out what you want to do.

I’d much, much rather hand-do the composition than abuse Haskell’s treatment of functions to dangle the composition function across function boundaries. I mean, really, what’s easier to understand:


f x = x + 2

h x = x * 2

print((f.h) 2)


or


f x = x + 2

h x = x * 2

c = (.) f

print((c h) 2)


Not to mention it uses a sort of weird property where it takes the usually-infix composition . and makes it a prefix operator. Normally it’s (f compose h), now you’re using it as compose(f, h).

Still, it’s only evil in that if you were using it in real code I’d smack you, it’s a perfectly reasonable homework question to make sure you get Haskell’s typing. It may be kind of bullshit as a test question, but for homework? It makes you think about how the type system and function chaining work under odd circumstances.

Well, yeah, in every real case I’d just write map . f instead of giving (.) map an alias.

I don’t think the switch between infix and prefix notation is a “weird property” though; it’s a simple and useful feature of the language, albeit useful mainly for doing exactly this sort of thing, using a normally infix operator in point-free style. But hey, maybe you just really like Lisp and you’d rather write (+) 3 4 instead of 3 + 4. :stuck_out_tongue:

And, you know, filling your codebase with ascii art of boobs.

Well, that’s the problem. That’s precisely the skill they want you to demonstrate: that you can carry out this mechanical procedure, thus demonstrating your understanding of the language mechanics, even if it would be quite atypical to actually write code in the provided style.

So what does “let f = (.) . (.)” translate to?

Well, first of all, let’s not bother with infix syntax. This is the same as saying “let f = (.) (.) (.)”.

Also, I’ll write “c” instead of a period for the composition operator (defined by c x y z = x (y z)). Sorry, boob fans.

Thus, we have “let f = c c c”. Now, c wants three arguments before doing anything, but we’ve only supplied it with two. So, let’s “eta-expand”: f x = c c c x = c (c x). Here, there’s a c given only one argument, but again, it wants three. So we eta-expand again: f x y z = c (c x) y z = c x (y z). And eta-expanding again: f x y z w = c x (y z) w = x (y z w).

We’re done now. There you have it: the declaration amounts to let f x y z w = x (y z w).

It’s not important that you ever write this as let f = c c c, but it is quite important that you understand how to evaluate c c c mechanically and thus can see that it produces this result!