Functional equivalent of overloading
What is the approach I should be taking in functional programming to overload a method (provide one or more different signatures with the same function name).
I'm new to functional programming, so I don't really get my head around this at the moment.
For example, in C# I'd have the following:
public int LowestCommonMultiple(int a, int b)
{
return (a * b) / GreatestCommonFactor(a, b); // details ommited
}
public int LowestCommonMultiple(List<int> integers)
{
int commonMultiple = integers[0];
foreach(var integer in integers)
{
commonMultiple = LowestCommonMultiple(commonMultiple, i);
}
return commonMultiple;
}
Thanks,
ED开发者_StackOverflow社区IT: I don't need the answer in C#, my question is more a functional pargadim question, for example, consider it in Haskell. I assume overloading a method is not an option.
In Haskell, overloading is done using type classes. This is quite different from overloading in C#, as type classes are more similar to interfaces in C#, although they are also more powerful*.
For example, to have a function which will be able to accept either an Integer
or a Bool
, you can write something like this:
class Foo a where
foo :: a -> String
instance Foo Integer where
foo n = show (n+42)
instance Foo Bool where
foo b = if b then "Hello" else "Goodbye"
Testing this out in the interpreter, we see that the function foo
has a type with constraints.
*Main> :t foo
foo :: Foo a => a -> String
This means that the function will work for types a
for which we have defined a Foo
instance.
*Main> foo 1295
"1337"
*Main> foo False
"Goodbye"
If we attempt to use it on a type for which there is no such instance, we get an error.
*Main> foo "Hello"
<interactive>:1:1:
No instance for (Foo [Char])
arising from a use of `foo'
Possible fix: add an instance declaration for (Foo [Char])
In the expression: foo "Hello"
In an equation for `it': it = foo "Hello"
For your example, I don't think it's very useful to overload this function in such a way in Haskell. In fact, the lcm
function in the standard library is already overloaded.
*Main> :t lcm
lcm :: Integral a => a -> a -> a
This means that it will work on any type for which there is an Integral
instance. In this case, that's all integer-like types, including the machine-sized Int
, the arbitrary-size Integer
, and others such as Int32
, Int64
and so on.
The list version can be written as foldl1' lcm
, so there might not be much of a need to provide such an overload in the first place.
* For one thing, type class instances are passed separately from the objects they apply to. This makes things like multiple dispatch a lot cleaner. This also means you can overload on the return type of a function, which would be impossible in C#. Type classes can also be used with type constructors; Monad
is perhaps the most famous example of such a type class.
I'm not sure what you mean by a functional programming language, this seems to have to do with a specific feature of any programming language (e.g., is overloading supported) rather than whether it is functional or object-oriented. In Javascript, for example, it is not supported, but is easily simulated because javascript doesn't require parameters to be passed and isn't strongly typed.
// a: array or integer
// b: optional integer when a is integer
function LowestCommonMultiple(a, b)
{
// could also test for presence of b, other validation checking probably good
if (a instanceof Array) {
// array code
} else {
return (a * b) / GreatestCommonFactor(a, b); // details ommited
}
}
The answer is going to be depend on the specific features of the language in question.
I don't think that your problem has much to do with functional vs procedural/OO programing but with static vs dynamic variable typing.
Take SML (a dialect of ML) and Scheme/Lisp for instance. Both functional languages, but it's a no brainer to overload a function in SML while it's impossible in Scheme (at least so it was when I was still using it). SML is statically typed (like C/C++/JAVA etc.) and therefore it's not problem for the compiler to use the variable types as a part of the signature and create overloads just like you any C compiler would create them for C code. Scheme on the other hand is dynamically typed and therefore the compiler/interpreter can't figure out a signature for the method based on it's parameters at compile time (in most cases).
Your question is very language pacific (I don't even think that all statically typed languages support function/method overloading) so it'll always come down to what language (and sometimes implementation) are you using.
you can write any count of signatures with one restruction - you can't have 2 signatures with equal parameter types. Every signature can have it's ow return type
void SomeMethor(){...}
string SomeMethod(string s){...}
object SomeMethod(string s, int i){...}
精彩评论