Fungsi ML dari tipe 'a ->' b

19

Profesor kami meminta kami untuk memikirkan fungsi dalam OCaml yang memiliki tipe

'a -> 'b

yaitu fungsi dari satu argumen yang bisa berupa apa saja, dan yang dapat mengembalikan apa pun yang berbeda.

Saya berpikir untuk menggunakan raisefungsi yang mengabaikan argumennya:

let f x = raise Exit

Tetapi profesor mengatakan ada solusi yang tidak memerlukan fungsi apa pun di perpustakaan standar. Saya bingung: bagaimana Anda bisa membuat 'bjika Anda tidak memilikinya?

Saya bertanya di sini daripada di Stack Overflow karena saya ingin memahami apa yang terjadi, saya tidak ingin hanya melihat program tanpa penjelasan.

Gilles 'SANGAT berhenti menjadi jahat'
sumber
2
Silakan menargetkan pemrograman pembelajaran siswa CS101 dalam jawaban Anda, bukan tipe teoretik yang mungkin mengilhami jawaban Anda nantinya.
Gilles 'SO- stop being evil'
Ini akan membantu jika Anda menjelaskan bagaimana Anda menemukan itu raiseakan berhasil, jadi kami tahu cara terbaik untuk menjelaskan mengapa solusi yang dicari oleh prof Anda (yang akan bekerja karena alasan yang sama dengan yang raiseberhasil) bekerja.
sepp2k
@ sepp2k raise : exn -> 'ajadi saya bisa mendapatkan nilai kembali, saya hanya mengabaikan argumen.
Gilles 'SO- stop being evil'
1
Pertanyaan tindak lanjut: Fungsi ML dari daftar polimorfik ke daftar polimorfik
Gilles 'SO- stop being evil'
2
Lihat juga. Mengapa algoritma Hindley-Milner tidak akan menghasilkan tipe seperti t1 -> t2? mendiskusikan pengaturan yang lebih teoretis.
Gilles 'SO- stop being evil'

Jawaban:

18

Kerangka itu let f x = BODY. Dalam BODY Anda harus menggunakan x-satunya cara generik (misalnya, jangan mengirimkannya ke fungsi yang mengharapkan bilangan bulat), dan Anda harus mengembalikan nilai dari setiap jenis lainnya. Tetapi bagaimana bagian yang terakhir itu benar? Satu-satunya cara untuk memenuhi pernyataan "untuk semua jenis 'b, nilai yang dikembalikan adalah nilai tipe 'b" adalah untuk memastikan fungsi tidak kembali. Sebenarnya ada dua kemungkinan: kesalahan BODY atau tidak berakhir. raiseKesalahan fungsi , berikut ini tidak berakhir:

let rec f x = f x
rgrig
sumber
19

Pertama, beberapa komentar. Dengan hanya menggunakan kalkulus lambda yang diketik inti, itu tidak mungkin diperoleh 'a -> 'bkarena sistem pengetikan dalam korespondensi (melalui isomorfisme Curry Howard ) dengan logika intuitionistic, dan formula yang sesuai A → Bbukanlah tautologi.

Ekstensi lain seperti tupel dan pencocokan / kondisional masih mempertahankan beberapa konsistensi logika menambahkan jenis produk *yang sesuai dengan ikat logis dan , dan menjumlahkan jenis |yang sesuai dengan atau . Sekali lagi, jangan berharap mereka menghasilkan 'a -> 'btipe itu, karena itu akan memungkinkan seseorang untuk membuktikan beberapa formula yang bukan tautologi.

Jadi, satu-satunya peluang Anda menggunakan konstruksi lain yang lolos dari logika seperti raise(tetapi Anda tidak diizinkan dalam hal ini) ... atau let rec! Rekursi memungkinkan untuk membangun program yang tidak pernah berakhir, dan hasilnya dapat diberikan jenis pengembalian sewenang-wenang karena tidak akan pernah diproduksi. Sekarang jika Anda berpikir tentang fungsi non terminating yang paling sepele (yang langsung memanggil dirinya untuk mengembalikan hasil):

let rec f x = f x

Anda akan melihat bahwa tipenya persis 'a -> 'b: apa pun argumen yang diberikan, hasilnya (yang tidak akan pernah dihitung) dapat dianggap memiliki tipe apa pun.

Tentu saja ini fbukan fungsi yang menarik, tapi itu intinya. Di OCaml, fungsi apa pun yang tipenya tidak terlihat seperti rumus yang valid adalah fungsi yang mencurigakan.

Stéphane Gimenez
sumber
Penanya tidak mengerti sepatah kata pun dari dua paragraf pertama Anda, tetapi saya menyukai kalimat Anda "hasil mereka dapat diberikan jenis pengembalian sewenang-wenang karena tidak akan pernah dihasilkan".
Gilles 'SO- stop being evil'
1

Menggunakan kompiler primitif Anda dapat menulis ini:

external magic: 'a -> 'b = "%identity"

(dan memang distribusi kompiler menyediakan ini, meskipun bukan bagian dari bahasa). Ini adalah pemeran identitas yang tidak aman.

Profesor Anda hampir pasti tidak menginginkan ini. Namun, ini juga satu-satunya fungsi yang berguna dengan tipe 'a -> 'byang saya ketahui, dan memang digunakan dalam distribusi OCaml itu sendiri.

Demi
sumber