Qu'entend-on exactement par «fonction partielle» dans la programmation fonctionnelle?

55

Selon ma compréhension, les fonctions partielles sont des fonctions que nous obtenons en passant moins de paramètres à une fonction que prévu. Par exemple, si cela était directement valide en Python:

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

Dans l'extrait ci-dessus, new_functionest une fonction partielle. Cependant, selon le Haskell Wiki , la définition de la fonction partielle est

Une fonction partielle est une fonction qui n'est pas définie pour tous les arguments possibles du type spécifié.

alors, ma question est: qu'est-ce qu'on entend exactement par "fonction partielle"?

Saurabh kukade
la source
37
Vous confondez une fonction partiellement appliquée avec une fonction partielle .
Willem Van Onsem
11
Python partialeffectue une application partielle , tandis que Haskell le fait automatiquement. L'entrée wiki fait référence aux fonctions partielles , qui est un terme issu des mathématiques.
L3viathan
9
À strictement parler, Haskell ne fait pas d'application de fonction partielle. Chaque fonction prend un argument et l'application de fonction applique une fonction à un seul argument. Currying simule ce que vous considéreriez comme une application partielle dans une autre langue en simulant des fonctions à arguments multiples en premier lieu. Quelque chose comme add 3 5n'est pas une application à fonction unique. Cela s'applique d'abord addà 3 pour obtenir une nouvelle fonction, qui est ensuite appliquée à 5.
chepner
Et en C #, une partialméthode est une déclaration directe d'une méthode privée éventuellement implémentée ailleurs dans la base de code du projet.
Dai
1
Votre exemple pourrait être rendu valide:new_function = functools.partial(add, 1)
wjandrea

Réponses:

76

Vous confondez ici deux concepts. Une fonction partiellement appliquée [haskell-wiki] avec une fonction partielle [haskell-wiki] .

Une fonction partiellement appliquée est:

Une application partielle dans Haskell implique de passer moins que le nombre total d'arguments à une fonction qui prend plusieurs arguments.

alors qu'une fonction partielle est en effet une fonction non totale:

Une fonction partielle est une fonction qui n'est pas définie pour tous les arguments possibles du type spécifié.

Willem Van Onsem
la source
24
C'est une bonne réponse, mais elle pourrait être améliorée en ajoutant un exemple de fonction partielle à la réponse elle-même.
ApproachingDarknessFish
2
Je ne suis pas sûr d'être d'accord avec cette définition exacte d'une fonction partiellement appliquée. Les fonctions dans Haskell ne prennent toujours qu'un seul argument, jamais "plusieurs arguments". J'utiliserais la définition "application partielle (application partielle de fonctions) dans Haskell implique de fournir moins que le nombre total d'arguments nécessaires pour obtenir une valeur qui ne peut pas être appliquée à un autre argument." (adapté d' ici )
TerryA
21

Une fonction partielle (à la fois dans le contexte de la programmation fonctionnelle et des mathématiques) est exactement ce que dit le wiki: une fonction non définie pour tous ses arguments possibles. Dans le contexte de la programmation, nous interprétons généralement "non défini" comme l'une des nombreuses choses, y compris le comportement indéfini, les exceptions ou la non-terminaison.

Un exemple de fonction partielle serait la division entière, qui n'est pas définie si le diviseur est 0 (dans Haskell, il générera une erreur).

dans l'extrait ci-dessus, new_function est une fonction partielle.

Ce code provoquerait simplement une erreur en Python, mais s'il fonctionnait comme vous le souhaitiez, ce serait une fonction totale (c'est-à-dire non partielle).

Comme les commentateurs l'ont déjà souligné, vous pensez très probablement au fait que ce serait une fonction partiellement appliquée .

sepp2k
la source
18

Les réponses expliquent tout, je vais juste ajouter un exemple dans chaque langue:

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

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

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

ce n'est ni une fonction partielle ni une fonction curry , c'est seulement une fonction à laquelle vous n'avez pas donné tous ses arguments .

Une fonction curry en python devrait ressembler à ceci:

partialAdd= lambda x: lambda y: x + y

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

4

et à haskell:

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

plusOne = plus 1

plusOne 4

5

Une fonction partielle en python:

def first(ls):
    return ls[0]

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

production

2

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

Et à Haskell, comme votre lien l'a montré:

head [1,2,3]
3

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

Alors qu'est-ce qu'une fonction totale?

Eh bien, fondamentalement le contraire: c'est une fonction qui fonctionnera pour n'importe quelle entrée de ce type. Voici un exemple en python:

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

et cela fonctionne même pour des listes infinies, si vous utilisez une petite astuce:

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]

Et l'équivalent en 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]

Ici, les fonctions ne se bloquent pas pour toujours. Le concept est le même: pour chaque liste, la fonction fonctionnera.

Damián Rafael Lattenero
la source
Il convient de mentionner que python prend en charge les fonctions partielles dans la bibliothèque standard.
Rétablissez Monica le