Mencoba menyusun yang tidak dapat digabungkan: kumpulkan semuanya

Dianjurkan agar Anda membaca artikel pertama jika Anda belum melakukannya. Artikel ini akan lebih pendek, kurang fokus pada detail dan lebih banyak pada kemampuan.

Menurut Stephen Diel , bersama dengan tipe dependen, kompilasi lebih cepat dan ambang masuk yang lebih rendah; efek aljabar adalah salah satu tugas paling penting yang akan diselesaikan di masa depan untuk Haskell.

Masa depan tidak jauh, jadi Anda harus mulai sekarang.

Meningkatkan Efek ke Efek Lain


class Liftable eff schema where lift :: eff ~> schema 

Apa yang dimaksud dengan "peningkatan" pada intinya? lift adalah murni / kembali sama, dengan pengecualian bahwa kita tidak merendam nilai dalam efek, tetapi efek dalam beberapa jenis transformator (dalam kasus kami, dalam rangkaian transformator):

 pure :: a -> ta lift :: ua -> tua 

Ini memungkinkan kita untuk menggunakan efek apa pun di dalam transformator tertentu - mudah untuk memperkenalkan efek baru, tetapi nanti kita perlu menafsirkan masing-masing dari mereka.

Dengan demikian, kita dapat menyusun efek yang diangkat dengan aman:

 let f = lift get :: Configured _ t => t _ let g = lift Nothing :: Optional t => t _ let h = lift (failure _) :: Failable _ t => t _ let x = f *> g *> h :: (Applicative t, Configured _ t, Optional t, Failable _ t) => t _ 

Dan kirimkan dalam urutan yang nyaman bagi kami:

 let y = pure _ :: Reader _ :> State _ :> Either _ :> Maybe := Int let z = pure _ :: State _ :> Either _ :> Maybe _ :> Reader := _ let x = f *> g *> h :: (Applicative t, Configured _ t, Optional t, Failable _ t) => t _ let xy = x *> y :: Reader _ :> State _ :> Either _ :> Maybe := _ let xz = x *> z :: State _ :> Either _ :> Maybe _ :> Reader := _ 

Adaptasi beberapa efek ke yang lain


 class Adaptable subeff eff | subeff -> eff where adapt :: subeff ~> eff 

Adaptasi berarti bahwa beberapa efek dapat diganti dengan efek yang lebih kuat. Misalnya, efek Reader dan Writer dapat digunakan di State , karena State dapat membaca dan menulis, dan dengan demikian mengubah nilai yang disimpan:

 lift put :: Accumulated _ t => t _ lift get :: Configured _ t => t _ (lift . adapt $ put) :: Stateful _ t => t _ (lift . adapt $ get) :: Stateful _ t => t _ 

Bagaimana ini mungkin? Dalam artikel sebelumnya, kami membagi Negara menjadi dua efek:

 State s = (->) s :. (,) s 

Dalam kasus Reader , kami cukup menaikkan functor panah ke tingkat Negara , dan dalam kasus Writer , tuple functor:

 Reader s = (->) s Writer s = (,) s 

Kami dapat menyesuaikan Failable ke Opsional , tetapi kami akan kehilangan informasi kesalahan:

 (lift $ Just _) :: Optional t => t _ (lift $ failure _) :: Failable _ t => t _ (lift . adapt $ failure _) :: Optional t => t _ 

Jalankan efek dalam transformer


Untuk menginterpretasikan efek dalam transformator, satu metode dijalankan sudah cukup:

 let xy = x *> y :: Reader _ :> State _ :> Either _ :> Maybe := _ let xy' = run xy _ :: State _ :> Either _ :> Maybe := _ let xy'' = run xy' _ :: Either _ :> Maybe := _ let xy''' = run xy'' :: Maybe (Either _) _ 

Kesimpulan dan Contoh


Jadi, saat ini, tanpa monad gratis / bebas (dan kadang-kadang bahkan tanpa monad), menggunakan sambungan Anda dapat mengetik ekspresi Anda sesuai dengan efek yang mereka hasilkan. Yang Anda butuhkan hanyalah komposisi functors.

Ada juga presentasi dari laporan tentang topik ini di reli lokal di Rostov-on-Don, yang dapat dilihat di browser.

Contoh terbaik adalah yang sedekat mungkin dengan kenyataan. Saya suka musik, sehingga Anda dapat melihat bagaimana sistem efek ini digunakan dalam program yang mengunduh album dari Bandcamp .

Source: https://habr.com/ru/post/id485518/


All Articles