Bagian yang rumit adalah loop. Mari kita mulai dengan itu. Sebuah loop biasanya dikonversi ke gaya fungsional dengan mengekspresikan iterasi dengan fungsi tunggal. Iterasi adalah transformasi dari variabel loop.
Berikut ini adalah implementasi fungsional dari loop umum:
loop : v -> (v -> v) -> (v -> Bool) -> v
loop init iter cond_to_cont =
if cond_to_cont init
then loop (iter init) iter cond
else init
Dibutuhkan (nilai awal dari variabel loop, fungsi yang mengekspresikan iterasi tunggal [pada variabel loop]) (suatu kondisi untuk melanjutkan loop).
Contoh Anda menggunakan loop pada array, yang juga rusak. Kemampuan ini dalam bahasa imperatif Anda dimasukkan ke dalam bahasa itu sendiri. Dalam pemrograman fungsional, kemampuan seperti itu biasanya diimplementasikan di tingkat perpustakaan. Berikut ini adalah kemungkinan implementasi
module Array (foldlc) where
foldlc : v -> (v -> e -> v) -> (v -> Bool) -> Array e -> v
foldlc init iter cond_to_cont arr =
loop
(init, 0)
(λ (val, next_pos) -> (iter val (at next_pos arr), next_pos + 1))
(λ (val, next_pos) -> and (cond_to_cont val) (next_pos < size arr))
Di dalamnya:
Saya menggunakan pasangan ((val, next_pos)) yang berisi variabel loop terlihat di luar dan posisi dalam array, yang menyembunyikan fungsi ini.
Fungsi iterasi sedikit lebih kompleks daripada di loop umum, versi ini memungkinkan untuk menggunakan elemen array saat ini. [Ini dalam bentuk kari .]
Fungsi seperti itu biasanya dinamai "lipat".
Saya meletakkan "l" dalam nama untuk menunjukkan bahwa akumulasi elemen-elemen array dilakukan dengan cara asosiatif-kiri; untuk meniru kebiasaan bahasa pemrograman imperatif untuk mengulangi array dari indeks rendah ke tinggi.
Saya meletakkan "c" dalam nama untuk menunjukkan bahwa versi lipatan ini mengambil kondisi yang mengontrol jika dan kapan loop harus dihentikan lebih awal.
Tentu saja fungsi utilitas seperti itu mungkin sudah tersedia di perpustakaan dasar yang dikirimkan dengan bahasa pemrograman fungsional yang digunakan. Saya menulisnya di sini untuk demonstrasi.
Sekarang kita memiliki semua alat yang ada dalam bahasa dalam kasus imperatif, kita dapat beralih untuk mengimplementasikan fungsionalitas spesifik dari contoh Anda.
Variabel dalam loop Anda adalah pasangan ('jawaban', boolean yang mengkodekan apakah akan melanjutkan).
iter : (Int, Bool) -> Int -> (Int, Bool)
iter (answer, cont) collection_element =
let new_answer = answer + collection_element
in case new_answer of
10 -> (new_answer, false)
150 -> (new_answer + 100, true)
_ -> (new_answer, true)
Perhatikan bahwa saya menggunakan "variabel" 'new_answer' baru. Ini karena dalam pemrograman fungsional saya tidak dapat mengubah nilai "variabel" yang sudah diinisialisasi. Saya tidak khawatir tentang kinerja, kompiler dapat menggunakan kembali memori 'jawaban' untuk 'new_answer' melalui analisis seumur hidup, jika dianggap lebih efisien.
Memasukkan ini ke dalam fungsi loop kami yang dikembangkan sebelumnya:
doSomeCalc :: Array Int -> Int
doSomeCalc arr = fst (Array.foldlc (0, true) iter snd arr)
"Array" di sini adalah nama modul yang mengekspor fungsi foldlc.
"kepalan", "kedua" singkatan dari fungsi yang mengembalikan komponen pertama, kedua dari parameter pasangannya
fst : (x, y) -> x
snd : (x, y) -> y
Dalam hal ini gaya "point-free" meningkatkan pembacaan implementasi doSomeCalc:
doSomeCalc = Array.foldlc (0, true) iter snd >>> fst
(>>>) adalah komposisi fungsi: (>>>) : (a -> b) -> (b -> c) -> (a -> c)
Sama seperti di atas, hanya parameter "arr" yang ditinggalkan dari kedua sisi persamaan yang menentukan.
Satu hal terakhir: memeriksa case (array == null). Dalam bahasa pemrograman yang dirancang lebih baik, tetapi bahkan dalam bahasa yang dirancang dengan buruk dengan beberapa disiplin dasar orang lebih suka menggunakan jenis opsional untuk mengekspresikan ketidak-ada-an. Ini tidak ada hubungannya dengan pemrograman fungsional, yang akhirnya menjadi pertanyaan, jadi saya tidak menghadapinya.
break
danreturn answer
dapat diganti denganreturn
di dalam loop. Dalam FP Anda dapat menerapkan pengembalian awal ini menggunakan kelanjutan, lihat mis. En.wikipedia.org/wiki/Continuation