2013-11-24 17 views
6

Monad'ın IO için Haskell'i nasıl kullandığını görebiliyorum - bu işlem için hesaplama etrafında bir kapsayıcı oluşturmak. Bir veri akışı işleminin işlevlerini oluşturacağınız gibi, “hesaplamaları bir araya getirme” için Monad'ları kullanabileceğiniz anlamına gelir.Kontrol Akışı için Monad'ler - Sıra, Seçim ve Yineleme

Sadece güldüğüm şey, Monad'ları Kontrol Akışı için kullanabilmenizdir. Şimdi Kontrol akışını, Sıralama, Seçim ve Yineleme ile ilgili olarak anlıyorum. Şimdi listelerde işlemleri gerçekleştirmek için harita, katlama, filtre ve zipwith/mapcat gibi yüksek mertebeden işlevlerde rahatım.

Sorum şu: - Kontrol akışını sağlamak için sıralama, seçim ve yineleme ile monad'ları yapabilir miyim? Haskell dizisi için

cevap

5

(Haskell, Scala veya Clojure içinde bir cevap Mutlu) , sen fonksiyonlara sahip >>= ve sequence:

(>>=) :: Monad m => m a -> (a -> m b) -> m b 
sequence :: Monad m => [m a] -> m [a] 

>>= veya bağlama işlevi, bir monadic harekete geçer değerini ayıklar ondan ve yeni bir monadik eylemi döndüren bir fonksiyona besler. sequence işlevi, aynı türdeki monadik eylemlerin bir listesini alır ve tümünü yürütür, sonuçlarını birleştirir ve tek bir eylem olarak sarar. yineleme için

sahip mapM ve forM (forM = flip mapM)

mapM :: Monad m => (a -> m b) -> [a] -> m [b] 

mapM ve forM fonksiyonlar, listedeki her bir öğe için bir eylem döndüren bir fonksiyonu uygulayan bir tek işlem olarak sonuçlar araya içindir.

Seçim için, Haskell'de uygulanan diğer koşullardan bağımsız olarak kullanılan koşulların kastettiğini kabul ediyorum. Saf ifadelerde kullanılabilecekleri gibi, doğrudan monadik ifadelerde de kullanılabilirler. Bununla birlikte, seçimleri yapmak veya en azından hataları işlemek için belirli monad'ları da kullanabilirsiniz. Bu çok basit bir uygulama vardır

data Maybe a = Nothing | Just a 

instance Monad Maybe where 
    return a = Just a 
    (Just a) >>= f = f a 
    Nothing >>= f = Nothing 

: grok en kolay Maybe monad olduğunu. Temel olarak, bir Nothing'u başka bir şeye dizilemeye çalışırsanız, her seferinde Nothing dönecektir. "foo" için arama başarısız olursa Burada

lookup :: Eq a => a -> [(a, b)] -> Maybe b 
-- Looks up a value in a key-value association list 

myFunc :: Int -> [(String, Int)] -> Maybe Int 
myFunc mult assocList = do 
    i <- lookup "foo" assocList 
    j <- lookup "bar" assocList 
    return $ i * mult + j 

, myFunc hemen Nothing döndürür: Bu size kısa devre arızası kavramını verir. Benzer şekilde, "bar" için arama başarısız olursa, myFunc hemen Nothing döndürür. Her iki arama da başarılı olursa myFunc herhangi bir hesaplama yapar. Bu bir çeşit "hata işleme" sağlar. Böyle bir dize hata mesajı ya da başarısızlık noktasında hesaplama devlet olarak bazı bağlamda, taşıyabilir "başarısızlık" değeri dışında çok aynı işleri benzer monad Either a

data Either a b = Left a | Right b 

instance Monad (Either a) where 
    return a = Right a 
    (Right a) >>= f = f a 
    (Left a) >>= f = Left a 

var.

+1

'>>' 'gerçekten sıralamayı garanti ediyor mu, yoksa sadece en yaygın monadların davranışı mı? – kqr

+1

@kqr Soruşturmayı sıralamayı garanti etmez, eğer sormak istediğiniz buysa.Bunun nedeni, değerlendirme sırasına göre '(>> =)' nin tanımına bağlıdır ve '(>> =)' ın tüm uygulamalarını ikincisinden önceki ilk argümanı değerlendirmez. –

+0

@kqr Sıralamayı garanti etmez, ama soruyu yorumlama olarak sorduğum 'do' gösterimini kullanmamıza izin veren işlevdir. Bağlama, bir do-deyimindeki her eylem için (ima edilen) noktalı virgülü esas olarak tanımladığından, belirli bir kod bloğu için kontrol akışının bir yönünü tanımlamanın bir yolunu sağlar. – bheklilr