Що саме означає "часткова функція" у функціональному програмуванні?


55

На моє розуміння, часткові функції - це функції, які ми отримуємо, передаючи менші параметри функції, ніж очікувалося. Наприклад, якщо це було прямо дійсним у Python:

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

У фрагменті, наведеному вище, new_functionє часткова функція. Однак, згідно з Haskell Wiki , визначення часткової функції є

Часткова функція - це функція, яка не визначена для всіх можливих аргументів зазначеного типу.

Отже, моє запитання: що саме мається на увазі під "частковою функцією"?


37
Ви плутаєте частково застосовану функцію з частковою функцією.
Віллем Ван Онсем

11
Python's partialвиконує часткове застосування , тоді як Haskell робить це автоматично. Запис у wiki стосується часткових функцій , що є терміном з математики.
L3viathan

9
Власне кажучи, Haskell не робить часткового застосування функції. Кожна функція бере один аргумент, а додаток функції застосовує функцію до одного аргументу. Проведення моделювання імітує те, що ви могли б вважати частковим додатком на іншій мові, в першу чергу імітуючи функції багатьох аргументів. Щось на кшталт add 3 5не є єдиним функціональним додатком. Це спочатку стосується add3, щоб отримати нову функцію, яка потім застосовується до 5.
Чепнер

І в C # partialметод - це пряма заява про необов'язково реалізований приватний метод в іншому місці кодової бази проекту.
Дай

1
Ваш приклад може бути зроблений правильний:new_function = functools.partial(add, 1)
wjandrea

Відповіді:


76

Вас тут плутають два поняття. Частково застосовуються функція [Haskell-віка] з частковою функцією [Haskell-віка] .

Частково застосована функція:

Часткове застосування в Haskell передбачає передачу менше, ніж повну кількість аргументів функції, яка приймає кілька аргументів.

тоді як часткова функція справді є неповною функцією:

Часткова функція - це функція, яка не визначена для всіх можливих аргументів зазначеного типу.


24
Це хороша відповідь, але її можна було б покращити, додавши приклад часткової функції до самої відповіді.
Наближення

2
Я не впевнений, що згоден з таким точним визначенням частково застосованої функції. Функції Haskell завжди беруть лише один аргумент, ніколи не "множинні аргументи". Я б застосував визначення "часткове застосування (частково застосував функції) в Haskell", передбачає подачу менше, ніж повну кількість аргументів, необхідних для отримання значення, яке не може бути додатково застосовано до іншого аргументу ". (адаптовано звідси )
TerryA

21

Часткова функція (як у контексті функціонального програмування, так і математики) - саме те, про що говорить вікі: функція, не визначена для всіх можливих аргументів. У контексті програмування ми зазвичай трактуємо "не визначено" як одну з кількох речей, включаючи невизначене поведінку, винятки або неприпинення.

Прикладом часткової функції може бути ціле ділення, яке не визначено, якщо дільник дорівнює 0 (у Haskell він видасть помилку).

у наведеному вище фрагменті new_function є частковою функцією.

Цей код просто спричинить помилку в Python, але якби він працював, як ви задумали, це була б тотальною (мається на увазі не частковою) функцією.

Як вже зазначали коментатори, ви, швидше за все, думаєте про те, що це буде частково застосована функція.


18

Відповіді все пояснюють, я просто додам один приклад на кожній мові:

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

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

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

це ні часткова функція, ні викрита функція , це лише функція, про яку ви не дали всіх своїх аргументів .

Вироблена функція в python має бути такою:

partialAdd= lambda x: lambda y: x + y

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

4

і в haskell:

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

plusOne = plus 1

plusOne 4

5

Часткова функція в пітоні:

def first(ls):
    return ls[0]

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

вихід

2

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

І в Haskell, як показало ваше посилання :

head [1,2,3]
3

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

Отже, що таке загальна функція?

Ну, в основному навпаки: це функція, яка буде працювати для будь-якого вводу цього типу. Ось приклад в python:

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

і це працює навіть для нескінченних списків, якщо ви використовуєте невелику хитрість:

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]

І еквівалент в 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]

Тут функції не висять назавжди. Концепція однакова: для кожного списку функціонуватиме.


Варто зазначити, що python підтримує часткові функції в стандартній бібліотеці.
Відновіть Моніку
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.