To be honest, I don’t think the non-partially applied versions are much less readable.
Also I’d like to think that even in non-curried languages the (.)
operator would be defined with 2 arguments and not with 3 arguments. So you’d still be able to write (I’ll write it with C style function application to make my point clearer):
break(p, l) = span(not . p, l)
Also, I think flip
should be defined with 1 argument and not 3, and foldl
with 2 arguments and not 3, so you’d be able to write:
reverse = foldl(flip((:)), [])
Or pointful:
reverse(l) = foldl(flip((:)), []))(l)
Note that this doesn’t require automatic currying where all arguments are always curried. It just requires being able to return functions as return type of a function. Not having automatic currying means f(x1,...,xn)(y)
is not interchangable with f(x1,...,xn,y)
, but it doesn’t mean functions cannot return functions as output.
Also for flip
in particular, it might be more readable to write a lambda anyway:
reverse(l) = foldl(\xs x -> x : xs, []))(l)
Edit: I’m now realizing that what I wrote above is actually against automatic currying and not against partial application (which could indeed really mean functions cannot return functions as output). If you really don’t want to use any partial application then the code would look like this:
break(p, l) = span(\x -> not(p(x)), l)
any(p, l) = or(map(p, l))
all(p, l) = and(map(p, l))
unlines(l) = concatMap(\l -> l ++ "\n", l)
reverse(l) = foldl(\xs x -> x : xs, [], l)
(flip
and (.)
, don’t make sense without partial application i.m.o.)
Still, I don’t think this is that much more cumbersome to read and write.