Apa perbedaannya?
Di Wikipedia, ada sedikit informasi dan tidak ada kode jelas yang menjelaskan istilah-istilah ini.
Apa saja contoh sederhana yang menjelaskan istilah-istilah ini?
Bagaimana korosi merupakan dual dari rekursi?
Apakah ada algoritma korususif klasik?
algorithms
recursion
pengguna167908
sumber
sumber
Jawaban:
Ada sejumlah cara bagus untuk melihat ini. Hal yang paling mudah bagi saya adalah berpikir tentang hubungan antara "Induktif" dan "definisi Coinductive"
Definisi induktif dari satu set seperti ini.
Set "Nat" didefinisikan sebagai set terkecil sehingga "Nol" berada di Nat, dan jika n ada di Nat "Succ n" ada di Nat.
Yang sesuai dengan Ocaml berikut
Satu hal yang perlu diperhatikan tentang definisi ini adalah angka
BUKAN anggota dari set ini. Mengapa? Asumsikan itu, sekarang pertimbangkan himpunan N yang memiliki semua elemen yang sama dengan Nat kecuali tidak memiliki omega. Jelas Zero ada di N, dan jika y ada di N, Succ (y) ada di N, tapi N lebih kecil dari Nat yang merupakan kontradiksi. Jadi, omega tidak ada di Nat.
Atau, mungkin lebih bermanfaat bagi ilmuwan komputer:
Diberikan beberapa himpunan "a", set "Daftar a" didefinisikan sebagai himpunan terkecil sehingga "Nil" ada dalam Daftar a, dan bahwa jika xs ada dalam Daftar a dan x adalah dalam "Cons x xs" ada dalam Daftar a.
Yang sesuai dengan sesuatu seperti
Kata yang digunakan di sini adalah "terkecil". Jika kita tidak mengatakan "terkecil" kita tidak akan memiliki cara untuk mengatakan jika set Nat mengandung pisang!
Lagi,
bukan definisi yang valid untuk daftar nats, seperti omega bukan Nat yang valid.
Mendefinisikan data secara induktif seperti ini memungkinkan kita untuk mendefinisikan fungsi yang bekerja dengannya menggunakan rekursi
kita kemudian dapat membuktikan fakta tentang ini, seperti "plus a Nol = a" menggunakan induksi (khusus, induksi struktural)
Bukti kami hasil dengan induksi struktural pada a.
Untuk kasing dasar, biarkan nol.
plus Zero Zero = match Zero with |Zero -> Zero | Succ(c) -> let r = plus c b in Succ(r)
jadi kami tahuplus Zero Zero = Zero
. Biarkana
menjadi nat. Asumsikan hipotesis induktif ituplus a Zero = a
. Kami sekarang menunjukkan bahwaplus (Succ(a)) Zero = Succ(a)
ini jelas sejakplus (Succ(a)) Zero = match a with |Zero -> Zero | Succ(a) -> let r = plus a Zero in Succ(r) = let r = a in Succ(r) = Succ(a)
demikian, dengan induksiplus a Zero = a
untuk semuaa
dalam natTentu saja kita dapat membuktikan hal-hal yang lebih menarik, tetapi ini adalah gagasan umum.
Sejauh ini kami telah menangani data yang terdefinisi secara induktif yang kami dapatkan dengan membiarkannya menjadi set "terkecil". Jadi sekarang kita ingin bekerja dengan codata yang didefinisikan secara coinductivly yang kita dapatkan dengan membiarkannya menjadi set terbesar.
Begitu
Biarkan satu set. Himpunan "Aliran a" didefinisikan sebagai himpunan terbesar sehingga untuk setiap x dalam aliran a, x terdiri dari pasangan berurutan (kepala, ekor) sehingga kepala berada di dalam dan ekor berada dalam aliran dari
Dalam Haskell kita akan menyatakan ini sebagai
Sebenarnya, di Haskell kita menggunakan daftar bawaan secara normal, yang bisa berupa pasangan yang dipesan atau daftar kosong.
Pisang juga bukan anggota jenis ini, karena pisang bukan pasangan yang dipesan atau daftar kosong. Tapi, sekarang bisa kita katakan
dan ini adalah definisi yang benar-benar valid. Terlebih lagi, kita dapat melakukan rekursi bersama pada data bersama ini. Sebenarnya, dimungkinkan untuk suatu fungsi bersifat ko-rekursif dan rekursif. Sementara rekursi didefinisikan oleh fungsi yang memiliki domain yang terdiri dari data, rekursi hanya berarti memiliki domain bersama (juga disebut rentang) yaitu data bersama. Rekursi primitif berarti selalu "memanggil diri sendiri" pada data yang lebih kecil hingga mencapai beberapa data terkecil. Rekursi bersama primitif selalu "menyebut dirinya" pada data yang lebih besar atau sama dengan apa yang Anda miliki sebelumnya.
secara primitif bersifat rekursif. Sementara fungsi
map
(semacam "pendahuluan" dalam bahasa imperatif) keduanya bersifat rekursif primitif (semacam) dan rekursif secara primitif.Hal yang sama berlaku untuk fungsi
zipWith
yang mengambil fungsi dan sepasang daftar dan menggabungkannya menggunakan fungsi itu.contoh klasik dari bahasa fungsional adalah deret Fibonacci
yang secara primitif bersifat rekursif, tetapi dapat diekspresikan secara lebih elegan sebagai daftar tanpa batas
contoh menarik dari induksi / coinduction membuktikan bahwa kedua definisi ini menghitung hal yang sama. Ini dibiarkan sebagai latihan untuk pembaca.
sumber
Pada dasarnya, korosi adalah gaya akumulator rekursi , membangun hasilnya pada jalan maju dari kasing awal, sedangkan rekursi reguler membangun hasilnya pada jalan kembali dari kasing dasar.
(Berbicara Haskell sekarang). Itu sebabnya
foldr
(dengan fungsi penggabungan yang ketat) mengekspresikan rekursi, danfoldl'
(dengan sisir yang ketat. F) /scanl
/until
/iterate
/unfoldr
/ dll mengekspresikan korosi. Koreksi ada di mana-mana.foldr
dengan sisir yang tidak ketat. f. mengekspresikan kontra modulo rekursi ekor .Dan rekursi yang dijaga Haskell sama seperti modulo rekursi ekor rekursi .
Ini adalah rekursi:
(baca
$
"dari"). Ini adalah koreksi:Lipatan: http://en.wikipedia.org/wiki/Fold_(higher-order_function)
sumber
Lihat ini di blog Vitomir Kovanovic . Saya menemukannya langsung:
sumber