68

根据我的理解,偏函数是我们通过向函数传递的参数少于预期得到的函数。例如,如果这在 Python 中直接有效:

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

在上面的代码片段中,new_function是一个偏函数。但是,根据Haskell Wiki,偏函数的定义是

偏函数是没有为指定类型的所有可能参数定义的函数。

所以,我的问题是:“部分功能”到底是什么意思?

4

3 回答 3

92

您在这里混淆了两个概念。一个部分应用的函数[haskell-wiki]和一个部分函数[haskell-wiki]

一个部分应用的函数是:

Haskell 中的部分应用涉及将少于全部数量的参数传递给接受多个参数的函数。

而偏函数确实是非全函数:

偏函数是没有为指定类型的所有可能参数定义的函数。

于 2019-10-11T10:15:47.133 回答
24

偏函数(在函数式编程和数学的上下文中)正是 wiki 所说的:一个没有为所有可能的参数定义的函数。在编程的上下文中,我们通常将“未定义”解释为几件事之一,包括未定义的行为、异常或未终止。

部分函数的一个例子是整数除法,如果除数为 0,则没有定义(在 Haskell 中它会抛出错误)。

在上面的代码片段中 new_function 是部分函数。

该代码只会在 Python 中导致错误,但如果它按您的预期工作,它将是一个总(意味着不是部分)函数。

正如评论者已经指出的那样,您很可能会想到它是一个部分应用的功能。

于 2019-10-11T10:19:08.077 回答
21

答案说明了一切,我只会在每种语言中添加一个示例:

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

在哈斯克尔:

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

在 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]

这里的功能不会永远挂起。概念是相同的:对于每个列表,该函数都将起作用。

于 2019-10-11T12:05:23.960 回答