Chính xác thì ý nghĩa của chức năng một phần là gì trong chương trình chức năng?


55

Theo hiểu biết của tôi, các hàm một phần là các hàm mà chúng ta có được bằng cách chuyển ít tham số hơn cho một hàm so với dự kiến. Ví dụ: nếu điều này là hợp lệ trực tiếp trong Python:

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

Trong đoạn trích trên, new_functionlà một phần chức năng. Tuy nhiên, theo Haskell Wiki , định nghĩa của chức năng một phần là

Hàm một phần là hàm không được xác định cho tất cả các đối số có thể có của loại đã chỉ định.

vì vậy, câu hỏi của tôi là: "chức năng một phần" nghĩa là gì?


37
Bạn đang nhầm lẫn một chức năng được áp dụng một phần với một phần chức năng.
Willem Van Onsem

11
Python partialthực hiện một phần ứng dụng , trong khi Haskell thực hiện điều đó một cách tự động. Mục wiki đề cập đến các chức năng một phần , là một thuật ngữ từ toán học.
L3viathan

9
Nói đúng ra, Haskell không làm ứng dụng chức năng một phần. Mỗi hàm lấy một đối số và ứng dụng hàm áp dụng một hàm cho một đối số. Currying mô phỏng những gì bạn sẽ nghĩ về ứng dụng một phần trong ngôn ngữ khác bằng cách mô phỏng các hàm nhiều đối số ở vị trí đầu tiên. Một cái gì đó giống như add 3 5không phải là một ứng dụng chức năng duy nhất. Điều này đầu tiên áp dụng addcho 3 để có được một chức năng mới, sau đó được áp dụng cho 5.
chepner

Và trong C #, một partialphương thức là một tuyên bố chuyển tiếp của một phương thức riêng được triển khai tùy chọn ở nơi khác trong cơ sở mã dự án.
Đại

1
Ví dụ của bạn có thể được xác thực:new_function = functools.partial(add, 1)
wjandrea

Câu trả lời:


76

Bạn đang ở đây khó hiểu hai khái niệm. Một phần áp dụng chức năng [Haskell-wiki] với một chức năng phần [Haskell-wiki] .

Một chức năng được áp dụng một phần là:

Ứng dụng một phần trong Haskell liên quan đến việc truyền ít hơn số lượng đối số đầy đủ cho một hàm có nhiều đối số.

trong khi đó một hàm một phần thực sự là một hàm không tổng:

Hàm một phần là hàm không được xác định cho tất cả các đối số có thể có của loại đã chỉ định.


24
Đây là một câu trả lời tốt, nhưng nó có thể được cải thiện bằng cách thêm một ví dụ về hàm một phần vào chính câu trả lời.
Tiếp

2
Tôi không chắc chắn tôi đồng ý với định nghĩa chính xác của chức năng được áp dụng một phần. Các hàm trong Haskell luôn chỉ lấy một đối số, không bao giờ "nhiều đối số". Tôi sẽ sử dụng định nghĩa "ứng dụng một phần (các hàm áp dụng một phần) trong Haskell liên quan đến việc cung cấp ít hơn toàn bộ số lượng đối số cần thiết để có được giá trị không thể áp dụng thêm cho đối số khác." (phỏng theo từ đây )
TerryA

21

Một hàm một phần (cả trong ngữ cảnh của lập trình hàm và toán học) chính xác như những gì wiki nói: một hàm không được xác định cho tất cả các đối số có thể có của nó. Trong ngữ cảnh lập trình, chúng ta thường hiểu "không được xác định" là một trong một số điều, bao gồm hành vi không xác định, ngoại lệ hoặc không chấm dứt.

Một ví dụ về hàm một phần sẽ là phép chia số nguyên, không được xác định nếu số chia là 0 (trong Haskell, nó sẽ đưa ra lỗi).

trong đoạn trích trên new_function là một phần chức năng.

Mã đó chỉ đơn giản là gây ra lỗi trong Python, nhưng nếu nó hoạt động như bạn dự định, thì đó sẽ là một hàm tổng (không phải là một phần).

Như các nhà bình luận đã chỉ ra, rất có thể bạn đang nghĩ về thực tế rằng đó là một chức năng được áp dụng một phần .


18

Các câu trả lời giải thích tất cả, tôi sẽ chỉ thêm một ví dụ trong mỗi ngôn ngữ:

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

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

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

Đây không phải là một phần chức năng cũng không phải là một chức năng bị quấy rối , đây chỉ là một chức năng mà bạn đã không đưa ra tất cả các đối số của nó .

Một hàm curried trong python nên như thế này:

partialAdd= lambda x: lambda y: x + y

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

4

và trong haskell:

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

plusOne = plus 1

plusOne 4

5

Một phần chức năng trong python:

def first(ls):
    return ls[0]

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

đầu ra

2

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

Và trong Haskell, khi liên kết của bạn xuất hiện:

head [1,2,3]
3

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

Vậy tổng hàm là gì?

Về cơ bản thì ngược lại: đây là một chức năng sẽ hoạt động cho bất kỳ đầu vào nào của loại đó. Đây là một ví dụ trong python:

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

và điều này hoạt động ngay cả đối với các danh sách vô hạn, nếu bạn sử dụng một mẹo nhỏ:

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]

Và tương đương trong 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]

Ở đây các chức năng không treo mãi mãi. Khái niệm này giống nhau: đối với mọi danh sách, hàm sẽ hoạt động.


Điều đáng nói là python có hỗ trợ các chức năng một phần trong thư viện chuẩn.
Phục hồi
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.