Was genau ist unter „Teilfunktion“ in der Funktionsprogrammierung zu verstehen?

55

Nach meinem Verständnis sind Teilfunktionen Funktionen, die wir erhalten, wenn wir weniger Parameter an eine Funktion übergeben als erwartet. Wenn dies beispielsweise in Python direkt gültig wäre:

>>> def add(x,y):
...    return x+y
... 
>>> new_function = add(1)
>>> new_function(2)
3

Im obigen Snippet new_functionist eine Teilfunktion. Laut Haskell Wiki ist die Definition der Teilfunktion jedoch

Eine Teilfunktion ist eine Funktion, die nicht für alle möglichen Argumente des angegebenen Typs definiert ist.

Meine Frage ist also: Was genau ist mit "Teilfunktion" gemeint?

Saurabh Kukade
quelle
37
Sie verwechseln eine teilweise angewendete Funktion mit einer Teilfunktion .
Willem Van Onsem
11
Python partialführt eine Teilanwendung durch , während Haskell dies automatisch tut. Der Wiki-Eintrag bezieht sich auf Teilfunktionen , ein Begriff aus der Mathematik.
L3viathan
9
Genau genommen führt Haskell keine Teilfunktionsanwendung durch. Jede Funktion akzeptiert ein Argument, und die Funktionsanwendung wendet eine Funktion auf ein einzelnes Argument an. Currying simuliert, was Sie als Teilanwendung in einer anderen Sprache betrachten würden, indem es zunächst Funktionen mit mehreren Argumenten simuliert. So etwas add 3 5ist keine Einzelfunktionsanwendung. Dies gilt zuerst für add3, um eine neue Funktion zu erhalten, die dann auf 5 angewendet wird.
chepner
In C # ist eine partialMethode eine Vorwärtsdeklaration einer optional implementierten privaten Methode an anderer Stelle in der Projektcodebasis.
Dai
1
Ihr Beispiel könnte gültig gemacht werden:new_function = functools.partial(add, 1)
wjandrea

Antworten:

76

Sie verwechseln hier zwei Konzepte. Eine teilweise angewendete Funktion [haskell-wiki] mit einer teilweise Funktion [haskell-wiki] .

Eine teilweise angewendete Funktion ist:

Bei einer Teilanwendung in Haskell wird weniger als die gesamte Anzahl von Argumenten an eine Funktion übergeben, die mehrere Argumente akzeptiert.

wohingegen eine Teilfunktion tatsächlich eine Nicht-Gesamtfunktion ist:

Eine Teilfunktion ist eine Funktion, die nicht für alle möglichen Argumente des angegebenen Typs definiert ist.

Willem Van Onsem
quelle
24
Dies ist eine gute Antwort, die jedoch verbessert werden könnte, indem der Antwort selbst ein Beispiel für eine Teilfunktion hinzugefügt wird.
Annäherung an
2
Ich bin mir nicht sicher, ob ich dieser genauen Definition einer teilweise angewendeten Funktion zustimme. Funktionen in Haskell verwenden immer nur ein Argument, niemals "mehrere Argumente". Ich würde die Definition "Teilanwendung (teilweise Anwendung von Funktionen) in Haskell beinhaltet die Bereitstellung von weniger als der vollen Anzahl von Argumenten, die erforderlich sind, um einen Wert zu erhalten, der nicht weiter auf ein anderes Argument angewendet werden kann." (angepasst von hier )
TerryA
21

Eine Teilfunktion (sowohl im Kontext der funktionalen Programmierung als auch der Mathematik) ist genau das, was das Wiki sagt: eine Funktion, die nicht für alle möglichen Argumente definiert ist. Im Zusammenhang mit der Programmierung interpretieren wir "nicht definiert" normalerweise als eines von mehreren Dingen, einschließlich undefiniertem Verhalten, Ausnahmen oder Nichtbeendigung.

Ein Beispiel für eine Teilfunktion wäre die Ganzzahldivision, die nicht definiert ist, wenn der Divisor 0 ist (in Haskell wird ein Fehler ausgegeben).

im obigen Snippet ist new_function eine Teilfunktion.

Dieser Code würde einfach einen Fehler in Python verursachen, aber wenn er wie beabsichtigt funktioniert, wäre er eine Gesamtfunktion (dh keine Teilfunktion).

Wie Kommentatoren bereits betont haben, denken Sie höchstwahrscheinlich an die Tatsache, dass es sich um eine teilweise angewendete Funktion handelt.

sepp2k
quelle
18

Die Antworten erklären alles, ich werde nur ein Beispiel in jeder Sprache hinzufügen:

def add(x,y):
    return x+y

f = add(1)
print(f(3))

    f = add(1)
TypeError: add() missing 1 required positional argument: 'y'

Dies ist weder eine Teilfunktion noch eine Curry-Funktion . Dies ist nur eine Funktion, für die Sie nicht alle Argumente angegeben haben .

Eine Curry-Funktion in Python sollte folgendermaßen aussehen:

partialAdd= lambda x: lambda y: x + y

plusOne = partialAdd(1)
print(plusOne(3))

4

und in haskell:

plus :: Int -> Int -> Int
plus x y = x + y

plusOne = plus 1

plusOne 4

5

Eine Teilfunktion in Python:

def first(ls):
    return ls[0]

print(first([2,4,5]))
print(first([]))

Ausgabe

2

print(first([]))
  File "main.py", line 2, in first
    return ls[0]
IndexError: list index out of range

Und in Haskell, wie Ihr Link zeigte:

head [1,2,3]
3

head []
*** Exception: Prelude.head: empty list

Was ist also eine Gesamtfunktion?

Im Grunde genommen das Gegenteil: Dies ist eine Funktion, die für alle Eingaben dieses Typs funktioniert. Hier ist ein Beispiel in Python:

def addElem(xs, x):
  xs.append(x)
  return xs

und dies funktioniert sogar für unendliche Listen, wenn Sie einen kleinen Trick verwenden:

def infiniList():
    count = 0
    ls = []
    while True:
        yield ls
        count += 1
        ls.append(count)

ls = infiniList()
for i in range(5):
  rs = next(ls)

print(rs, addElem(rs,6))

[1, 2, 3, 4]
[1, 2, 3, 4, 5] [1, 2, 3, 4, 5]

Und das Äquivalent in Haskell:

addElem :: a -> [a] -> [a]
addElem x xs = x : xs

addElem 3 (take 10 [1..])
=> [3,1,2,3,4,5,6,7,8,9,10]

Hier hängen die Funktionen nicht für immer. Das Konzept ist das gleiche: Für jede Liste funktioniert die Funktion.

Damián Rafael Lattenero
quelle
Erwähnenswert ist, dass Python Teilfunktionen in der Standardbibliothek unterstützt.
Setzen Sie Monica