>>20
Unfortunately that is not possible with normal haskell. But you can do this in template haskell, which is a very crude form of macro's. (Scheme's macros are superior) That is what the approach in (3) is too. It is a macro, you call then. (Calling convention: [macro|body|]) or you can also call them as $(gFlip 1 2 3 f). Calling convention is like a normal function $(function <parameters>). The function here is a real function emitting haskell AST.
And it probably can be done in a dependent language with pi types, but haskell isn't dependently typed and it is not easy to program in those languages. It means that the type system has a special type, which accepts an type as argument:
f: PI(x: A),B(x) is a function, where the type of B is dependent on the type of A.
if B(x) = const C x then f becomes PI(x : A), const C x and reduces to A -> C.
With this we could create a function flipT which accepts a natural and throws out the correct type of B for a general flip function. flipT should look something like this (pseudocode):
flipT 1 2 = (a -> b -> c -> d) -> b -> a -> c -> d
flipT 3 1 = (a -> b -> c -> d) -> c -> b -> a -> d
etc.
But this is only half of the puzzle. We didn't add the type of f . Thus flipT would be a function with two inputs flipT, because we need to know the arity of f in advance and don't like to rely on the user for it's input. It think it will be rather difficult, but interesting.