Saya berasal dari latar belakang C #, di mana LINQ berevolusi menjadi Rx.NET, tetapi selalu memiliki minat pada FP. Setelah beberapa pengantar untuk monad dan beberapa proyek sampingan di F #, saya siap untuk mencoba dan melangkah ke tingkat berikutnya.
Sekarang, setelah beberapa pembicaraan tentang monad gratis dari orang-orang dari Scala, dan beberapa artikel di Haskell, atau F #, saya telah menemukan tata bahasa dengan penerjemah untuk pemahaman yang sangat mirip dengan IObservable
rantai.
Di FRP Anda membuat definisi operasi dari potongan spesifik domain yang lebih kecil termasuk efek samping dan kegagalan yang tetap ada di dalam rantai, dan memodelkan aplikasi Anda sebagai serangkaian operasi dan efek samping. Dalam monad gratis, jika saya mengerti dengan benar, Anda melakukan hal yang sama dengan menjadikan operasi Anda sebagai functors, dan mengangkatnya menggunakan coyoneda.
Apa perbedaan antara keduanya yang memiringkan jarum ke salah satu pendekatan? Apa perbedaan mendasar ketika mendefinisikan layanan atau program Anda?
sumber
Cont
satu-satunya monad yang saya lihat menyarankan yang tidak dapat diekspresikan melalui monad gratis, orang mungkin dapat berasumsi bahwa FRP bisa. Seperti bisa hampir hal lain .IObservable
adalah turunan dari kelanjutan monad.Jawaban:
Monad
Sebuah monad terdiri dari
Seorang petugas akhir . Dalam dunia rekayasa perangkat lunak kami, kami dapat mengatakan ini terkait dengan tipe data dengan parameter tipe tunggal yang tidak dibatasi. Dalam C #, ini akan menjadi sesuatu dari bentuk:
Dua operasi yang didefinisikan pada tipe data itu:
return
Sayapure
mengambil nilai "murni" (yaituT
nilai) dan "membungkusnya" ke dalam monad (yaitu, menghasilkanM<T>
nilai). Karenareturn
kata kunci dicadangkan dalam C #, saya akan gunakanpure
untuk merujuk ke operasi ini mulai sekarang. Dalam C #,pure
akan menjadi metode dengan tanda tangan seperti:bind
/flatmap
mengambil nilai monadik (M<A>
) dan fungsif
.f
mengambil nilai murni dan mengembalikan nilai monadik (M<B>
). Dari ini,bind
menghasilkan nilai monadik baru (M<B>
).bind
memiliki tanda tangan C # berikut:Juga, untuk menjadi seorang monad,
pure
danbind
diharuskan untuk mematuhi tiga hukum monad.Sekarang, salah satu cara untuk memodelkan monads di C # adalah dengan membangun antarmuka:
(Catatan: Agar semuanya singkat dan ekspresif, saya akan mengambil beberapa kebebasan dengan kode di seluruh jawaban ini.)
Sekarang kita dapat mengimplementasikan monad untuk datagypes konkret dengan mengimplementasikan implementasi konkret dari
Monad<M>
. Misalnya, kami dapat menerapkan monad berikut untukIEnumerable
:(Saya sengaja menggunakan sintaks LINQ untuk memanggil hubungan antara sintaks LINQ dan monad. Tetapi perhatikan kita bisa mengganti kueri LINQ dengan panggilan ke
SelectMany
.)Sekarang, bisakah kita mendefinisikan monad
IObservable
? Tampaknya begitu:Untuk memastikan kita memiliki monad, kita perlu membuktikan hukum monad. Ini bisa non-sepele (dan saya tidak cukup akrab dengan Rx.NET untuk mengetahui apakah mereka bahkan dapat dibuktikan dari spesifikasinya saja), tetapi ini merupakan awal yang menjanjikan. Untuk memudahkan diskusi ini, mari kita asumsikan hukum monad berlaku dalam kasus ini.
Monads gratis
Tidak ada "monad gratis" tunggal. Sebaliknya, monad gratis adalah kelas monad yang dibangun dari functors. Artinya, diberi fungsi
F
, kita dapat secara otomatis memperoleh monad untukF
(yaitu, monad gratisF
).Functors
Seperti Monads, functors dapat didefinisikan oleh tiga item berikut:
Dua operasi:
pure
membungkus nilai murni ke dalam functor. Ini analog denganpure
untuk monad. Bahkan, untuk functors yang juga merupakan monad, keduanya harus identik.fmap
memetakan nilai dalam input ke nilai baru dalam output melalui fungsi yang diberikan. Tanda tangan itu adalah:Seperti halnya monad, functors diharuskan untuk mematuhi hukum functor.
Mirip dengan monads, kita dapat memodelkan functors melalui antarmuka berikut:
Sekarang, karena monad adalah sub-kelas dari fungsi, kita juga bisa
Monad
sedikit refactor :Di sini saya telah menambahkan metode tambahan
join
,, dan memberikan implementasi standar keduanyajoin
danbind
. Perhatikan, bagaimanapun, bahwa ini adalah definisi melingkar. Jadi, Anda harus menimpa setidaknya satu atau yang lain. Juga, perhatikan bahwapure
sekarang diwarisi dariFunctor
.IObservable
dan Monads GratisSekarang, karena kita telah mendefinisikan sebuah monad untuk
IObservable
dan karena monad adalah sub-kelas dari fungsi, maka kita harus dapat mendefinisikan instance dari functor untukIObservable
. Inilah satu definisi:Sekarang kita memiliki functor yang ditentukan
IObservable
, kita dapat membangun monad gratis dari functor itu. Dan itulah tepatnya bagaimanaIObservable
hubungannya dengan monad gratis - yaitu, bahwa kita dapat membangun monad gratis dariIObservable
.sumber