Что именно подразумевается под "частичной функцией" в функциональном программировании?

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

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

В приведенном выше фрагменте new_function является частичной функцией. Однако, согласно Haskell Wiki, определение частичной функции:

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

Итак, мой вопрос: что именно подразумевается под "частичной функцией"?

Ответы

Ответ 1

Вы здесь путаете две концепции. частично примененная функция [haskell-wiki] с частичной функцией [haskell-wiki].

Частично примененная функция:

Частичное применение в Haskell включает в себя передачу меньше полного числа аргументов функции, которая принимает несколько аргументов.

в то время как частичная функция действительно является неполной функцией:

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

Ответ 2

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

Примером частичной функции может служить целочисленное деление, которое не определено, если делитель равен 0 (в Хаскеле это приведет к ошибке).

в приведенном выше фрагменте new_function является частичной функцией.

Этот код просто вызовет ошибку в Python, но если он будет работать так, как вы хотели, это будет полная (то есть не частичная) функция.

Как уже отмечали комментаторы, вы, скорее всего, думаете о том, что это будет частично примененная функция.

Ответ 3

Ответы объясняют все, я просто добавлю один пример на каждом языке:

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

Частичная функция в Python:

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

А в Хаскеле, как показала ваша ссылка :

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]

И эквивалент в Хаскеле:

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]

Здесь функции не зависают вечно. Концепция одинакова: для каждого списка функция будет работать.

Ответ 4

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

Что мне очень непонятно в этом определении, так это часть: is a function that is not defined

Лучшим описанием частичной функции (IMO) будет:

Частичная функция - это функция, вызывающая другую существующую функцию с одним или несколькими параметрами - этой существующей функции - предварительно определенной.

А затем пример, чтобы пойти с ним:

from functools import partial

def multiply(x,y):              #<< existing function
    return x * y

dbl = partial(multiply,2) .     #<< new function with 'predefined' parameter(s)
print(dbl(4))

Хорошее место, чтобы узнать больше об этих частичных функциях:

https://www.learnpython.org/en/Partial_functions

EDIT:

Смотрите комментарии ниже. Хотя многие люди в Интернете в примерах и учебных пособиях ссылаются на понятие частичных чисел как partial functions, это не правильно.

Это вызываемый объект, который будет вести себя как функция, которую вы ему дали.

В официальных документах Python говорится:

functools.partial(func[,*args][, **keywords])

Вернуть новый частичный объект, который при вызове будет вести себя как func, вызываемый с помощью аргументов позиционных аргументов и ключевых слов аргументов. Если для вызова передается больше аргументов, они добавляются к аргументам. Если предоставляются дополнительные аргументы ключевых слов, они расширяют и переопределяют ключевые слова.

https://docs.python.org/2/library/functools.html

PS: это означает, что этот ответ не правильный, но все же в некоторой степени связан с путаницей в названии. Я оставлю это как таковой.