Apa sebenarnya yang dimaksud dengan "fungsi parsial" dalam pemrograman fungsional?

55

Menurut pemahaman saya, fungsi parsial adalah fungsi yang kita dapatkan dengan melewatkan lebih sedikit parameter ke fungsi daripada yang diharapkan. Misalnya, jika ini secara langsung valid dengan Python:

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

Dalam cuplikan di atas, new_functionadalah fungsi parsial. Namun, menurut Haskell Wiki , definisi fungsi parsial adalah

Fungsi parsial adalah fungsi yang tidak didefinisikan untuk semua argumen yang mungkin dari tipe yang ditentukan.

jadi, pertanyaan saya adalah: apa sebenarnya yang dimaksud dengan "fungsi parsial"?

Saurabh kukade
sumber
37
Anda mengacaukan fungsi yang diterapkan sebagian dengan fungsi sebagian .
Willem Van Onsem
11
Python partialmelakukan aplikasi parsial , sedangkan Haskell melakukannya secara otomatis. Entri wiki mengacu pada fungsi parsial , yang merupakan istilah dari matematika.
L3viathan
9
Sebenarnya, Haskell tidak melakukan aplikasi fungsi parsial. Setiap fungsi mengambil satu argumen, dan aplikasi fungsi menerapkan fungsi ke satu argumen. Currying mensimulasikan apa yang Anda anggap sebagai aplikasi parsial dalam bahasa lain dengan mensimulasikan fungsi multi-argumen. Sesuatu seperti add 3 5bukan aplikasi fungsi tunggal. Ini berlaku pertama adduntuk 3 untuk mendapatkan fungsi baru, yang kemudian diterapkan ke 5.
chepner
Dan dalam C #, partialmetode adalah deklarasi maju dari metode pribadi yang diimplementasikan secara opsional di tempat lain dalam basis kode proyek.
Dai
1
Contoh Anda dapat dibuat valid:new_function = functools.partial(add, 1)
wjandrea

Jawaban:

76

Anda di sini membingungkan dua konsep. Sebuah sebagian diterapkan fungsi [Haskell-wiki] dengan fungsi parsial [Haskell-wiki] .

Fungsi yang diterapkan sebagian adalah:

Aplikasi parsial di Haskell melibatkan pengoperan argumen yang kurang dari jumlah penuh ke suatu fungsi yang membutuhkan banyak argumen.

sedangkan fungsi parsial memang adalah fungsi non-total:

Fungsi parsial adalah fungsi yang tidak didefinisikan untuk semua argumen yang mungkin dari tipe yang ditentukan.

Willem Van Onsem
sumber
24
Ini adalah jawaban yang baik, tetapi bisa diperbaiki dengan menambahkan contoh fungsi parsial ke jawaban itu sendiri.
ApproachingDarknessFish
2
Saya tidak yakin saya setuju dengan definisi yang tepat dari fungsi yang diterapkan sebagian. Fungsi di Haskell selalu hanya mengambil satu argumen, tidak pernah "banyak argumen". Saya akan menggunakan definisi "aplikasi parsial (sebagian menerapkan fungsi) di Haskell melibatkan penyediaan lebih sedikit dari jumlah argumen yang diperlukan untuk mendapatkan nilai yang tidak dapat lebih lanjut diterapkan pada argumen lain." (Diadaptasi dari sini )
TerryA
21

Fungsi parsial (baik dalam konteks pemrograman fungsional dan matematika) persis seperti yang dikatakan wiki: fungsi yang tidak didefinisikan untuk semua argumen yang mungkin. Dalam konteks pemrograman, kami biasanya mengartikan "tidak didefinisikan" sebagai salah satu dari beberapa hal, termasuk perilaku yang tidak terdefinisi, pengecualian atau non-terminasi.

Contoh dari fungsi parsial adalah pembagian integer, yang tidak didefinisikan jika pembagi adalah 0 (dalam Haskell akan menimbulkan kesalahan).

di snippet new_function adalah fungsi parsial.

Kode itu hanya akan menyebabkan kesalahan dalam Python, tetapi jika itu berfungsi seperti yang Anda inginkan, itu akan menjadi fungsi total (artinya tidak parsial).

Seperti yang sudah ditunjukkan oleh para komentator, Anda kemungkinan besar memikirkan fakta bahwa itu akan berfungsi sebagian .

sepp2k
sumber
18

Jawabannya menjelaskan semua, saya hanya akan menambahkan satu contoh di setiap bahasa:

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

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

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

ini bukan fungsi parsial atau fungsi kari , ini hanya fungsi yang Anda tidak memberikan semua argumennya .

Fungsi kari dalam python harus seperti ini:

partialAdd= lambda x: lambda y: x + y

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

4

dan di haskell:

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

plusOne = plus 1

plusOne 4

5

Fungsi parsial dalam python:

def first(ls):
    return ls[0]

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

keluaran

2

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

Dan di Haskell, saat tautan Anda muncul:

head [1,2,3]
3

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

Jadi apa fungsi total?

Yah, pada dasarnya yang sebaliknya: ini adalah fungsi yang akan bekerja untuk input apa pun dari jenis itu. Berikut ini adalah contoh dalam python:

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

dan ini berfungsi bahkan untuk daftar tak terbatas, jika Anda menggunakan sedikit trik:

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]

Dan yang setara dalam 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]

Di sini fungsinya tidak menggantung selamanya. Konsepnya sama: untuk setiap daftar fungsi akan bekerja.

Damián Rafael Lattenero
sumber
Layak disebutkan bahwa python memiliki dukungan untuk fungsi parsial di pustaka standar.
Pasang kembali Monica