Функциональный эквивалент перегрузки - PullRequest
3 голосов
/ 07 июня 2011

Какой подход я должен использовать в функциональном программировании для перегрузки метода (предоставить одну или несколько разных подписей с одинаковым именем функции).

Я новичок в функциональном программировании, поэтому я нев настоящий момент я не могу этого понять.

Например, в C # у меня будет следующее:

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;
}

Спасибо,

РЕДАКТИРОВАТЬ: яМне не нужен ответ в C #, мой вопрос - скорее функциональный вопрос, например, рассмотрим его на Haskell.Я предполагаю, что перегрузка метода не вариант.

Ответы [ 4 ]

2 голосов
/ 29 августа 2011

В Haskell перегрузка выполняется с использованием классов типов .Это сильно отличается от перегрузки в C #, поскольку классы типов больше похожи на интерфейсы в C #, хотя они также более мощные *.

Например, иметь функцию, которая сможет принимать либо Integer или Bool, вы можете написать что-то вроде этого:

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"

Проверяя это в интерпретаторе, мы видим, что функция foo имеет тип с ограничениями.

*Main> :t foo
foo :: Foo a => a -> String

Это означает, что функция будет работать для типов a, для которых мы определили экземпляр Foo.

*Main> foo 1295
"1337"
*Main> foo False
"Goodbye"

Если мы попытаемся использовать его для типадля которого нет такого экземпляра, мы получаем ошибку.

*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"

Для вашего примера, я не думаю, что очень полезно перегрузить эту функцию таким способом в Haskell.Фактически, функция lcm в стандартной библиотеке уже перегружена.

*Main> :t lcm
lcm :: Integral a => a -> a -> a

Это означает, что она будет работать с любым типом, для которого существует экземпляр Integral.В данном случае это все целочисленные типы, включая машинный размер Int, произвольный размер Integer и другие, такие как Int32, Int64 и т. Д.

Версия списка может быть записана как foldl1' lcm, поэтому в первую очередь такая перегрузка может не потребоваться.

* С одной стороны, экземпляры класса типов передаются отдельно отобъекты, к которым они относятся.Это делает такие вещи, как многократная отправка, намного чище.Это также означает, что вы можете перегрузить возвращаемый тип функции, что было бы невозможно в C #.Классы типов также могут использоваться с конструкторами типа ;Monad, пожалуй, самый известный пример такого типа классов.

0 голосов
/ 07 июня 2011

Я не уверен, что вы подразумеваете под функциональным языком программирования, похоже, это связано с определенной особенностью любого языка программирования (например, поддерживается перегрузка), а не с тем, является ли он функциональным или объектно-ориентированным. Например, в Javascript он не поддерживается, но его легко смоделировать, потому что javascript не требует передачи параметров и не является строго типизированным.

// 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
    }
}

Ответ будет зависеть от специфики рассматриваемого языка.

0 голосов
/ 07 июня 2011

Я не думаю, что ваша проблема во многом связана с функциональным или процедурным / ОО-программированием, но со статической или динамической типизацией переменных.

Возьмите, например, SML (диалект ML) и Scheme / Lisp,Оба функциональных языка, но перегрузить функцию в SML нетрудно, хотя в Scheme это невозможно (по крайней мере, так было, когда я еще ее использовал).SML имеет статическую типизацию (например, C / C ++ / JAVA и т. Д.), И поэтому для компилятора не проблема использовать типы переменных как часть сигнатуры и создавать перегрузки, как вы любой C-компилятор создавал бы для кода C.Схема, с другой стороны, динамически типизируется, и поэтому компилятор / интерпретатор не может определить сигнатуру для метода на основе его параметров во время компиляции (в большинстве случаев).

Ваш вопрос очень языковой (Я даже не думаю, что все статически типизированные языки поддерживают перегрузку функций / методов), поэтому всегда будет зависеть, какой язык (а иногда и реализацию) вы используете.

0 голосов
/ 07 июня 2011

вы можете написать любое количество подписей с одной реструктуризацией - вы не можете иметь 2 подписи с одинаковыми типами параметровКаждая подпись может иметь свой тип возврата

void SomeMethor(){...}
string SomeMethod(string s){...}
object SomeMethod(string s, int i){...}
...