Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is currying the same as overloading?

Is currying for functional programming the same as overloading for OO programming? If not, why? (with examples if possible)

Tks

like image 606
Marcelo de Aguiar Avatar asked May 16 '12 00:05

Marcelo de Aguiar


People also ask

What is the other name for function overloading?

In Java, function overloading is also known as compile-time polymorphism and static polymorphism. Function overloading should not be confused with forms of polymorphism where the choice is made at runtime, e.g. through virtual functions, instead of statically.

When would you use a currying function?

Currying is helpful when you have to frequently call a function with a fixed argument. Considering, for example, the following function: If we want to define the function error , warn , and info , for every type, we have two options. Currying provides a shorter, concise, and more readable solution.

Which of the following is not considered in overloading?

Solution. The destructor function cannot be overloaded.


2 Answers

Currying is not specific to functional programming, and overloading is not specific to object-oriented programming.

"Currying" is the use of functions to which you can pass fewer arguments than required to obtain a function of the remaining arguments. i.e. if we have a function plus which takes two integer arguments and returns their sum, then we can pass the single argument 1 to plus and the result is a function for adding 1 to things.

In Haskellish syntax (with function application by adjacency):

plusOne = plusCurried 1
three = plusOne 2
four = plusCurried 2 2
five = plusUncurried 2 3

In vaguely Cish syntax (with function application by parentheses):

plusOne = plusCurried(1)
three = plusOne(2)
four = plusCurried(2)(2)
five = plusUncurried(2, 3)

You can see in both of these examples that plusCurried is invoked on only 1 argument, and the result is something that can be bound to a variable and then invoked on another argument. The reason that you're thinking of currying as a functional-programming concept is that it sees the most use in functional languages whose syntax has application by adjacency, because in that syntax currying becomes very natural. The applications of plusCurried and plusUncurried to define four and five in the Haskellish syntax merge to become completely indistinguishable, so you can just have all functions be fully curried always (i.e. have every function be a function of exactly one argument, only some of them will return other functions that can then be applied to more arguments). Whereas in the Cish syntax with application by parenthesised argument lists, the definitions of four and five look completely different, so you need to distinguish between plusCurried and plusUncurried. Also, the imperative languages that led to today's object-oriented languages never had the ability to bind functions to variables or pass them to other functions (this is known as having first-class functions), and without that facility there's nothing you can actually do with a curried-function other than invoke it on all arguments, and so no point in having them. Some of today's OO languages still don't have first-class functions, or only gained them recently.

The term currying also refers to the process of turning a function of multiple arguments into one that takes a single argument and returns another function (which takes a single argument, and may return another function which ...), and "uncurrying" can refer to the process of doing the reverse conversion.


Overloading is an entirely unrelated concept. Overloading a name means giving multiple definitions with different characteristics (argument types, number of arguments, return type, etc), and have the compiler resolve which definition is meant by a given appearance of the name by the context in which it appears.

A fairly obvious example of this is that we could define plus to add integers, but also use the same name plus for adding floating point numbers, and we could potentially use it for concatenating strings, arrays, lists, etc, or to add vectors or matrices. All of these have very different implementations that have nothing to do with each other as far as the language implementation is concerned, but we just happened to give them the same name. The compiler is then responsible for figuring out that plus stringA stringB should call the string plus (and return a string), while plus intX intY should call the integer plus (and return an integer).

Again, there is no inherent reason why this concept is an "OO concept" rather than a functional programming concept. It simply happened that it fit quite naturally in statically typed object-oriented languages that were developed; if you're already resolving which method to call by the object that the method is invoked on, then it's a small stretch to allow more general overloading. Completely ad-hoc overloading (where you do nothing more than define the same name multiple times and trust the compiler to figure it out) doesn't fit as nicely in languages with first-class functions, because when you pass the overloaded name as a function itself you don't have the calling context to help you figure out which definition is intended (and programmers may get confused if what they really wanted was to pass all the overloaded definitions). Haskell developed type classes as a more principled way of using overloading; these effectively do allow you to pass all the overloaded definitions at once, and also allow the type system to express types a bit like "any type for which the functions f and g are defined".


In summary:

  • currying and overloading are completely unrelated
  • currying is about applying functions to fewer arguments than they require in order to get a function of the remaining arguments
  • overloading is about providing multiple definitions for the same name and having the compiler select which definition is used each time the name is used
  • neither currying nor overloading are specific to either functional programming or object-oriented programming; they each simply happen to be more widespread in historical languages of one kind or another because of the way the languages developed, causing them to be more useful or more obvious in one kind of language
like image 77
Ben Avatar answered Oct 17 '22 06:10

Ben


No, they are entirely unrelated and dissimilar.

Overloading is a technique for allowing the same code to be used at different types -- often known in functional programming as polymorphism (of various forms).

A polymorphic function:

 map :: (a -> b) -> [a] -> [b]
 map f []     = []
 map f (x:xs) = f x : map f xs

Here, map is a function that operates on any list. It is polymorphic -- it works just as well with a list of Int as a list of trees of hashtables. It also is higher-order, in that it is a function that takes a function as an argument.

Currying is the transformation of a function that takes a structure of n arguments, into a chain of functions each taking one argument.

In curried languages, you can apply any function to some of its arguments, yielding a function that takes the rest of the arguments. The partially-applied function is a closure.

And you can transform a curried function into an uncurried one (and vice-versa) by applying the transformation invented by Curry and Schonfinkel.

curry :: ((a, b) -> c) -> a -> b -> c 
   -- curry converts an uncurried function to a curried function.

uncurry :: (a -> b -> c) -> (a, b) -> c
   -- uncurry converts a curried function to a function on pairs.
like image 27
Don Stewart Avatar answered Oct 17 '22 07:10

Don Stewart