Cosa si intende esattamente per "funzione parziale" nella programmazione funzionale?


55

Secondo la mia comprensione, le funzioni parziali sono funzioni che otteniamo passando meno parametri a una funzione del previsto. Ad esempio, se questo fosse direttamente valido in Python:

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

Nel frammento sopra, new_functionè una funzione parziale. Tuttavia, secondo Haskell Wiki , la definizione di funzione parziale è

Una funzione parziale è una funzione che non è definita per tutti i possibili argomenti del tipo specificato.

quindi, la mia domanda è: cosa si intende esattamente per "funzione parziale"?


37
Stai confondendo una funzione parzialmente applicata con una funzione parziale .
Willem Van Onsem,

11
Python partialesegue un'applicazione parziale , mentre Haskell lo fa automaticamente. La voce wiki si riferisce a funzioni parziali , che è un termine della matematica.
L3viathan,

9
A rigor di termini, Haskell non esegue un'applicazione con funzioni parziali. Ogni funzione accetta un argomento e l'applicazione di funzione applica una funzione a un singolo argomento. Currying simula ciò che potresti pensare come un'applicazione parziale in un'altra lingua simulando in primo luogo funzioni a argomento multiplo. Qualcosa del genere add 3 5non è un'applicazione a singola funzione. Questo vale addper 3 per ottenere una nuova funzione, che viene quindi applicata a 5.
chepner,

E in C #, un partialmetodo è una dichiarazione diretta di un metodo privato facoltativamente implementato altrove nella base di codice del progetto.
Dai,

1
Il tuo esempio potrebbe essere reso valido:new_function = functools.partial(add, 1)
wjandrea,

Risposte:


76

Qui stai confondendo due concetti. Una funzione parzialmente applicata [haskell-wiki] con una funzione parziale [haskell-wiki] .

Una funzione parzialmente applicata è:

L'applicazione parziale in Haskell comporta il passaggio di meno del numero completo di argomenti a una funzione che accetta più argomenti.

mentre una funzione parziale è in effetti una funzione non totale:

Una funzione parziale è una funzione che non è definita per tutti i possibili argomenti del tipo specificato.


24
Questa è una buona risposta, ma potrebbe essere migliorata aggiungendo un esempio di una funzione parziale alla risposta stessa.
Avvicinamento

2
Non sono sicuro di essere d'accordo con la definizione esatta di una funzione parzialmente applicata. Le funzioni in Haskell accettano sempre solo un argomento, mai "argomenti multipli". Vorrei usare la definizione "applicazione parziale (applicazione parziale delle funzioni) in Haskell implica fornire meno del numero completo di argomenti necessari per ottenere un valore che non può essere ulteriormente applicato a un altro argomento". (adattato da qui )
TerryA

21

Una funzione parziale (sia nel contesto della programmazione funzionale che della matematica) è esattamente ciò che dice il wiki: una funzione non definita per tutti i suoi possibili argomenti. Nel contesto della programmazione, di solito interpretiamo "non definito" come una delle varie cose, tra cui comportamenti indefiniti, eccezioni o non terminazione.

Un esempio di una funzione parziale sarebbe la divisione intera, che non è definita se il divisore è 0 (in Haskell genererà un errore).

nello snippet sopra new_function è la funzione parziale.

Quel codice causerebbe semplicemente un errore in Python, ma se funzionasse come previsto, sarebbe una funzione totale (che significa non parziale).

Come già sottolineato dai commentatori, molto probabilmente stai pensando al fatto che sarebbe una funzione parzialmente applicata .


18

Le risposte spiegano tutto, aggiungerò solo un esempio in ogni lingua:

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

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

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

questa non è né una funzione parziale né una funzione curry , questa è solo una funzione a cui non hai fornito tutti i suoi argomenti .

Una funzione al curry in Python dovrebbe essere così:

partialAdd= lambda x: lambda y: x + y

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

4

e in haskell:

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

plusOne = plus 1

plusOne 4

5

Una funzione parziale in Python:

def first(ls):
    return ls[0]

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

produzione

2

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

E in Haskell, come è apparso il tuo link :

head [1,2,3]
3

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

Quindi cos'è una funzione totale?

Bene, sostanzialmente il contrario: questa è una funzione che funzionerà per qualsiasi input di quel tipo. Ecco un esempio in Python:

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

e questo funziona anche per liste infinite, se usi un piccolo trucco:

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]

E l'equivalente 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]

Qui le funzioni non si bloccano per sempre. Il concetto è lo stesso: per ogni elenco la funzione funzionerà.


Vale la pena ricordare che Python supporta le funzioni parziali nella libreria standard.
Ripristina Monica il
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.