Iterated currying and mapping — better solutions?

I wanted to have curry, uncurry and fmap that work for functions of any arity.

Are there better solutions?

I know there are simpler solutions, but some complexity is necessary if one wishes to have type inference: only the most trivial type families can be admitted to be one to one by GHC, and in more complicated cases one has to resort to an uneasy mix of type families and classes equipped with functional dependencies, for which the algorithm in GHC is more flexible.

My motivation for writing these functions is from working with servant, where client (Proxy @Endpoint) can be a function of any number of arguments, depending on the Endpoint specification, so code that wants to work with any client has to be polymorphic in the number of arguments.

See also my previous inquiry into fancy programming.

My own attempt at writing a “multi-curry” function is here, motivated, like yours, by a need to transform functions independently of their number of arguments.

In order for it to work, I had to restrict the allowable functions to those that have a certain concrete monad at the “tip”. Otherwise the compiler finds difficult to determine what is the true “tip” of the function (I did not want to use overlapping instances.)

Instead of reinventing some inductive tuple, I used the NP type from sop-core for storing the uncurried parameters.