Baru-baru ini, saya mencoba menggunakan Haskell di beberapa sistem produksi kasus nyata saya. Sistem tipe Haskell benar-benar menawarkan saya bantuan besar. Sebagai contoh, ketika saya menyadari bahwa saya memerlukan beberapa fungsi tipe
f :: (Foldable t, Monad m) => ( a-> b -> m b) -> b -> t a -> m b
Sebenarnya ada fungsi seperti foldM
, foldlM
dan foldrM
.
Namun, yang sangat mengejutkan saya adalah definisi dari fungsi-fungsi ini, seperti:
foldlM :: (Foldable t, Monad m) => (b -> a -> m b) -> b -> t a -> m b
foldlM f z0 xs = foldr f' return xs z0
where f' x k z = f z x >>= k
jadi fungsi f'
harus bertipe:
f' :: a -> b -> b
seperti yang disyaratkan foldr
, maka b
harus dari jenis *-> m *
, sehingga seluruh definisi foldlM
bisa masuk akal.
Contoh lain termasuk definisi liftA2
dan<*>
(<*>) :: f (a -> b) -> f a -> f b
(<*>) = liftA2 id
liftA2 :: (a -> b -> c) -> f a -> f b -> f c
liftA2 f x = (<*>) (fmap f x)
Saya mencoba beberapa solusi saya sendiri sebelum mengintip ke dalam kode sumber. Tetapi celahnya sangat besar sehingga saya tidak berpikir saya bisa menemukan solusi ini, tidak peduli berapa banyak baris kode yang akan saya tulis di masa depan.
Jadi pertanyaan saya adalah, pengetahuan seperti apa atau cabang matematika spesifik apa yang diperlukan seseorang untuk bernalar pada tingkat yang sangat abstrak.
Saya tahu Teori Kategori mungkin menawarkan bantuan dan saya telah mengikuti kuliah yang luar biasa ini sejak lama dan masih mengerjakannya.
sumber
Jawaban:
Secara umum, dll logika, saya akan membayangkan. Tetapi Anda juga dapat mempelajarinya dengan melakukannya. :) Dengan waktu Anda memperhatikan beberapa pola, ambil beberapa trik.
Seperti ini
foldr
dengan argumen tambahan. Beberapa melihatnya sebagai fungsi lipat sehingga mereka dapat digabungkan melalui.
danid
(yang kadang - kadang benar-benar<=<
danreturn
),Beberapa merasa lebih mudah untuk memahaminya dalam istilah sintaksis yang lebih sederhana
jadi ketika
g
tidak ketat dalam argumen kedua,s
bisa berfungsi sebagai keadaan yang diteruskan dari kiri, meskipun kita melipat di sebelah kanan, sebagai salah satu contoh.sumber
Jadi cara terbaik untuk memahaminya adalah dengan melakukannya. Di bawah ini ada implementasi
foldlM
penggunaanfoldl
alih-alihfoldr
. Ini latihan yang bagus, coba dan dapatkan solusi yang saya sarankan. Contoh menjelaskan semua alasan yang saya lakukan untuk mencapainya, yang mungkin berbeda dari Anda, dan mungkin bias karena saya sudah tahu tentang menggunakan fungsi akumulator.Langkah 1 : Mari kita coba menulis
foldlM
dalam bentukfoldl
Di sini Anda menyadari bahwa
f'
itu murni dan Anda harus mengekstraksi hasilf
mengetik. Satu-satunya cara untuk 'mengekstraksi' nilai monadik adalah dengan>>=
operator, tetapi operator seperti itu harus dibungkus tepat setelah digunakan.Jadi sebagai kesimpulan: Setiap kali Anda berakhir dengan saya ingin sepenuhnya membuka monad ini , menyerah saja. Bukan jalan yang benar
Langkah 2 : Mari kita coba menulis
foldlM
dalam bentukfoldl
tetapi pertama menggunakan[]
sebagai lipat, karena mudah untuk mencocokkan pola (yaitu kita tidak benar-benar perlu menggunakanfold
)Oke, itu mudah. Mari kita bandingkan definisi dengan
foldl
definisi biasa untuk daftarKeren!! mereka hampir sama. Kasus sepele adalah tentang hal yang persis sama. Kasus rekursif adalah sedikit berbeda sedikit, Anda ingin menulis sesuatu yang lebih seperti:
foldlM' f (f z0 x) xs
. Tetapi tidak dikompilasi seperti pada langkah 1, jadi Anda mungkin berpikir OK, saya tidak ingin menerapkanf
, hanya untuk memegang perhitungan seperti itu dan menyusunnya>>=
. Saya ingin menulis sesuatu yang lebih sukafoldlM' f (f z0 x >>=) xs
jika itu masuk akal ...Langkah 3 Sadarilah bahwa yang ingin Anda kumpulkan adalah komposisi fungsi dan bukan hasil. (di sini saya mungkin bias oleh fakta bahwa saya sudah mengetahuinya karena Anda telah mempostingnya ).
Dengan tipe
initFunc
dan menggunakan pengetahuan kita dari langkah 2 (definisi rekursif) kita dapat menyimpulkan ituinitFunc = return
. Definisif'
dapat diselesaikan mengetahui yangf'
harus digunakanf
dan>>=
.Seperti yang Anda lihat, tidak sangaaaat sulit untuk melakukannya. Itu perlu latihan, tapi saya bukan pengembang haskell profesional dan saya bisa melakukannya sendiri, ini soal latihan
sumber
Monad
contoh yang khas .Anda tidak perlu pengetahuan khusus dalam matematika untuk menulis fungsi seperti
foldM
. Saya menggunakan Haskell dalam produksi selama 4 tahun, dan saya juga berjuang untuk memahami definisi inifoldM
. Tetapi itu sebagian besar karena itu ditulis dengan buruk. Tolong, jangan menganggapnya sebagai kesalahan pribadi jika Anda tidak dapat memahami beberapa kode yang tidak jelas. Ini adalah versi yang lebih mudah dibaca darifoldlM
Fungsi ini masih bukan yang termudah. Sebagian besar karena memiliki penggunaan non-khas di
foldr
mana akumulator menengah adalah suatu fungsi. Tetapi Anda dapat melihat beberapa orang yang membuat definisi seperti itu lebih mudah dibaca:where
(sehingga Anda tahu bentuk argumen).Setelah melihat fungsi seperti itu, Anda sekarang dapat melakukan teknik penalaran Equasional untuk memperluas definisi langkah demi langkah dan melihat cara kerjanya. Kemampuan untuk datang dengan fungsi seperti itu datang dengan pengalaman. Saya tidak memiliki keterampilan matematika yang kuat, dan fungsi ini bukan fungsi Haskell yang khas. Tetapi semakin banyak latihan yang Anda miliki, semakin baik :)
sumber