“ ฟังก์ชั่นบางส่วน” ในการเขียนโปรแกรมฟังก์ชั่นคืออะไร?


55

ตามความเข้าใจของฉันฟังก์ชั่นบางส่วนเป็นฟังก์ชั่นที่เราได้รับโดยส่งพารามิเตอร์น้อยลงไปยังฟังก์ชั่นมากกว่าที่คาด ตัวอย่างเช่นถ้าสิ่งนี้ถูกต้องใน Python โดยตรง:

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

ในตัวอย่างด้านบนnew_functionเป็นฟังก์ชันบางส่วน อย่างไรก็ตามตามHaskell Wikiความหมายของฟังก์ชั่นบางส่วนคือ

ฟังก์ชั่นบางส่วนเป็นฟังก์ชั่นที่ไม่ได้กำหนดไว้สำหรับข้อโต้แย้งที่เป็นไปได้ทั้งหมดของประเภทที่ระบุ

ดังนั้นคำถามของฉันคืออะไร "ฟังก์ชั่นบางส่วน" หมายถึงอะไร?


37
คุณกำลังสับสนกับฟังก์ชั่นที่ใช้บางส่วนกับฟังก์ชั่นบางส่วน
Willem Van Onsem

11
partialดำเนินการประยุกต์ใช้บางส่วนในขณะที่ Haskell ไม่ว่าโดยอัตโนมัติ รายการ wiki หมายถึงฟังก์ชั่นบางส่วนซึ่งเป็นคำจากคณิตศาสตร์
L3viathan

9
Haskell พูดอย่างเคร่งครัดไม่ได้ทำแอปพลิเคชันฟังก์ชันบางส่วน ทุกฟังก์ชั่นรับหนึ่งอาร์กิวเมนต์และแอปพลิเคชันฟังก์ชั่นใช้ฟังก์ชั่นกับอาร์กิวเมนต์เดียว การจำลองจะจำลองสิ่งที่คุณคิดว่าเป็นแอพพลิเคชั่นบางส่วนในภาษาอื่นโดยจำลองฟังก์ชันหลายอาร์กิวเมนต์ในตอนแรก สิ่งที่ชอบadd 3 5ไม่ใช่แอปพลิเคชันฟังก์ชันเดียว ครั้งแรกนี้ใช้addกับ 3 เพื่อรับฟังก์ชั่นใหม่ซึ่งจะนำไปใช้กับ 5
chepner

และใน C # partialเมธอดคือการประกาศไปข้างหน้าของเมธอดไพรเวตที่ถูกนำไปใช้งานแบบเป็นทางเลือกที่อื่นในโค้ดเบสของโครงการ
Dai

1
ตัวอย่างของคุณสามารถใช้งานได้:new_function = functools.partial(add, 1)
wjandrea

คำตอบ:


76

คุณอยู่ที่นี่ทำให้สับสนสองแนวคิด บางส่วนนำไปใช้ฟังก์ชั่น [Haskell-wiki]พร้อมกับฟังก์ชั่นบางส่วน [Haskell-wiki]

ฟังก์ชั่นที่ใช้บางส่วนคือ:

แอปพลิเคชั่นบางส่วนใน Haskell เกี่ยวข้องกับการส่งผ่านน้อยกว่าจำนวนอาร์กิวเมนต์เต็มไปยังฟังก์ชันที่รับอาร์กิวเมนต์หลายตัว

ในขณะที่ฟังก์ชั่นบางส่วนแน่นอนเป็นฟังก์ชั่นที่ไม่ใช่ทั้งหมด:

ฟังก์ชั่นบางส่วนเป็นฟังก์ชั่นที่ไม่ได้กำหนดไว้สำหรับข้อโต้แย้งที่เป็นไปได้ทั้งหมดของประเภทที่ระบุ


24
นี่เป็นคำตอบที่ดี แต่ก็สามารถปรับปรุงได้โดยการเพิ่มตัวอย่างของฟังก์ชันบางส่วนในคำตอบนั้นเอง
ApproachingDarknessFish

2
ฉันไม่แน่ใจว่าฉันเห็นด้วยกับคำจำกัดความที่แน่นอนของฟังก์ชันที่นำไปใช้บางส่วน ฟังก์ชั่นใน Haskell จะรับเพียงหนึ่งอาร์กิวเมนต์เท่านั้นไม่ต้อง "ขัดแย้งหลายครั้ง" ฉันจะใช้คำจำกัดความ "บางส่วนของแอปพลิเคชัน (บางส่วนใช้ฟังก์ชั่น) ใน Haskell เกี่ยวข้องกับการจัดหาน้อยกว่าจำนวนเต็มของข้อโต้แย้งที่จำเป็นในการรับค่าที่ไม่สามารถนำไปใช้กับอาร์กิวเมนต์อื่น" (ดัดแปลงมาจากที่นี่ )
TerryA

21

ฟังก์ชั่นบางส่วน (ทั้งในบริบทของฟังก์ชั่นการเขียนโปรแกรมและคณิตศาสตร์) เป็นสิ่งที่ wiki พูดว่า: ฟังก์ชั่นที่ไม่ได้กำหนดไว้สำหรับอาร์กิวเมนต์ที่เป็นไปได้ทั้งหมด ในบริบทของการเขียนโปรแกรมเรามักจะตีความว่า "ไม่ได้กำหนด" เป็นหนึ่งในหลายสิ่งรวมถึงพฤติกรรมที่ไม่ได้กำหนดข้อยกเว้นหรือการเลิกจ้าง

ตัวอย่างของฟังก์ชั่นบางส่วนจะเป็นการหารจำนวนเต็มซึ่งไม่ได้กำหนดไว้หากตัวหารคือ 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'

นี่ไม่ใช่ฟังก์ชันบางส่วนหรือฟังก์ชัน curriedนี่เป็นเพียงฟังก์ชันที่คุณไม่ได้ให้ข้อโต้แย้งทั้งหมด

ฟังก์ชั่น curried ในไพ ธ อนควรเป็นดังนี้:

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

ฟังก์ชั่นรวมคืออะไร?

ตรงข้ามโดยทั่วไป: นี่คือฟังก์ชั่นที่จะทำงานกับอินพุตประเภทใด นี่คือตัวอย่างในไพ ธ อน:

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]

ที่นี่ฟังก์ชั่นไม่แขวนตลอดไป แนวคิดเหมือนกัน: สำหรับทุกรายการฟังก์ชันจะทำงาน


มันเป็นมูลค่าการกล่าวขวัญว่าหลามมีการสนับสนุนสำหรับฟังก์ชั่นบางส่วนในห้องสมุดมาตรฐาน
Reinstate Monica
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.