Ini merupakan tindak lanjut dari jawaban atas pertanyaan saya sebelumnya.
Misalkan saya perlu untuk memetakan setiap item a:A
dari List[A]
untuk b:B
dengan fungsi def f(a:A, leftNeighbors:List[A]): B
dan menghasilkan List[B]
.
Jelas saya tidak bisa begitu saja memanggil map
daftar tetapi saya bisa menggunakan daftar ritsleting . Ritsleting adalah kursor untuk bergerak di sekitar daftar. Ini menyediakan akses ke elemen saat ini ( focus
) dan tetangganya.
Sekarang saya bisa mengganti f
dengan saya def f'(z:Zipper[A]):B = f(z.focus, z.left)
dan meneruskan fungsi baru ini f'
ke cobind
metode Zipper[A]
.
Cara cobind
kerjanya seperti ini: ia menyebutnya f'
dengan ritsleting, lalu memindahkan ritsleting, memanggil f'
dengan ritsleting baru yang "dipindahkan", memindahkan ritsleting lagi dan seterusnya, dan seterusnya ... hingga ritsleting mencapai akhir daftar.
Akhirnya, cobind
mengembalikan jenis ritsleting baru Zipper[B]
, yang dapat diubah ke daftar dan masalah terpecahkan.
Sekarang perhatikan simetri antara cobind[A](f:Zipper[A] => B):Zipper[B]
dan bind[A](f:A => List[B]):List[B]
Itu sebabnya List
adalah a Monad
dan Zipper
adalah a Comonad
.
Apakah masuk akal ?