Alternatif untuk Defungsionalisasi

10

Defungsionalisasi adalah transformasi yang pertama kali dijelaskan pada tahun 1972 oleh John C. Reynolds untuk menghilangkan fungsi tingkat tinggi. Apakah ada transformasi alternatif (lebih efisien?) Untuk menghilangkan fungsi tingkat tinggi?

Peter
sumber

Jawaban:

6

Ada tiga pendekatan utama (yang saya ketahui) untuk mengimplementasikan fungsi tingkat tinggi. Defungsionalisasi, konversi penutupan / pengangkatan lambda, dan kombinator.

Tulis Mari untuk jenis fungsi tingkat tinggi dari ke dan untuk jenis pointer fungsi C-gaya dari ke . (Jika kita ingin memformalkan ini, kita dapat mengatakan bahwa abstraksi penunjuk fungsi hanya diperbolehkan di lingkungan kosong.)SEBUAHBSEBUAHBSEBUAHBSEBUAHB

Konversi penutupan adalah gagasan bahwa kita memilih representasi The biasanya akan menjadi tuple memegang nilai-nilai variabel bebas di lokasi lambda abstraksi. Bisa jadi itu adalah representasi lain.

SEBUAHBE.(E,(E,SEBUAH)B)
E

Pengangkatan Lambda mengambil pendekatan yang agak berbeda dan lebih global di mana abstraksi lambda ditarik keluar ke dalam lingkup berisi menambahkan variabel bebas sebagai parameter di sepanjang jalan, sampai mencapai lingkup tingkat atas. Meskipun ini berkaitan dengan penataan blok, untuk benar-benar menangani penggunaan fungsi tingkat tinggi memerlukan aplikasi parsial. Anda kemudian dapat membagikan fungsi yang diterapkan sebagian, tetapi ini pada dasarnya representasi yang sama dengan konversi penutupan.

Jika Anda ingin menghilangkan pointer fungsi, kami dapat menggunakan defungsionalisasi, yang, dalam kasus khusus ini, hanya menghasilkan enumerasi. Ada sedikit alasan untuk melakukan ini, karena fungsi pointer adalah konstruksi alami di sebagian besar bahasa assembly.

Pendekatan selanjutnya adalah menggunakan kombinator. Ini pada dasarnya sama dengan lambda mengangkat dan menggunakan aplikasi parsial kecuali satu set fungsi tingkat atas tetap digunakan, dan semua fungsi lainnya dinyatakan sebagai kombinasi dari mereka. (Jika mereka tidak memiliki seperangkat kombinator tetap yang telah ditentukan, maka ini biasanya hanya pendekatan berbasis lambda seperti yang saya jelaskan di atas.) Fungsi urutan lebih tinggi kemudian secara efektif diwakili oleh nilai dalam tipe data menggunakan sintaks Haskell seperti berikut ini (menggunakan SKkombinator ):

data CA = S | K | App CA CA -- plus other things in reality, like primitive values

Representasi yang lebih mirip dengan kalkulus tulang belakang mungkin lebih masuk akal untuk efisiensi. Atau Anda dapat melakukan sesuatu seperti:

data CA = S0 | S1 CA | S2 CA CA | K0 | K1 CA  

Menerapkan fungsi urutan lebih tinggi terbagi menjadi dua kasus: kombinator telah sepenuhnya diterapkan dan karenanya harus dijalankan, atau kami mengembalikan nilai baru yang mewakili aplikasi (sebagian).

Saya belum melakukan survei mendalam, tapi saya cukup yakin variasi konversi penutupan adalah strategi implementasi yang paling umum untuk fungsi tingkat tinggi (karenanya sering disebut "penutupan"). Ini memiliki sifat yang bagus menjadi modular, sederhana, dan cukup efisien bahkan dalam bentuk naifnya. Dibutuhkan pilihan yang baik dari kombinator dasar dan beberapa kepintaran untuk mendapatkan pendekatan berbasis kombinator untuk berkinerja baik. Defungsionalisasi memang tidak banyak digunakan sejauh yang saya tahu, tetapi ada sedikit alasan untuk tidak memanfaatkan fungsi pointer. Sejauh yang Anda lakukan, misalnya, alih-alih analisis kasus besar Anda memiliki tabel pointer fungsi yang Anda indekskan, pada dasarnya Anda telah menciptakan konversi penutupan.

Ada beberapa pendekatan lain. Salah satunya adalah instantiasi template yang pada dasarnya untuk mengambil pengurangan secara harfiah, dan secara sederhana mengganti istilah menjadi istilah lain. Biasanya, ini membutuhkan memiliki dan memanipulasi sintaksis struktur seperti pohon abstrak. Fungsi-fungsi tingkat tinggi kemudian diwakili oleh istilah lambda (sintaksis) atau "templat" -nya yang dapat menyederhanakan melakukan penggantian.β

Derek Elkins meninggalkan SE
sumber