2012-01-20 12 views
5

Bu Monad Transformers ile ilk tanışıklığımdır, bu yüzden cevap açık olabilir.Monad transformatörünün içindeki monadın sonucu

Diyelim ki bir tür blokta yer aldım StateT MyMonad MyType, aynı türde başka bir işlev yapmak istiyorum, hem durumu değiştirip, hem de MyMonad MyType türünde bir değer döndürdüm. Bunu nasıl başarabilirim? Sanırım örnekler here bunu guessSession'da gösteriyor, ancak nasıl uygulanacağını anlayamıyorum! Eğer bir monad transformatör içinde yatan monad kullanmak istiyorsanız

+1

: http: // www.haskell.org/hoogle – jberryman

cevap

9

, sen lift kullanabilirsiniz:

lift :: (MonadTrans t, Monad m) => m a -> t m a 

Bu durumda, tStateT MyState ve mMyMonad olduğunu. Yani, örneğin:

foo :: StateT MyState MyMonad MyType 
foo = do 
    modify $ \s -> s+1 
    lift $ doSomethingInMyMonad 42 

Monad transformatörler Eğer içeriden tip MyMonad MyType değerini döneceğini anlamda "konulu katmanlı" değildir; Daha fazla literal bir dönüşümü:, bir monad'i dönüştürülmüş monadde eylemleri yürütme yeteneğine sahip yeni bir taneye dönüştürürler. StateT s m'u sadece State s monad olarak düşünebilirsiniz, ancak m'daki eylemleri StateT s m'daki eylemlere dönüştürmek için lift'u da kullanabilirsiniz. vb StateT, ReaderT gibi standart Monad Transformer Library (mtl) transformatörleri kullanıyorsanız

, gerçekte lift kullanmak gerekmez; modify ve ask gibi şeyler, numaralı herhangi bir monadında, yığındaki bir yere doğru trafo ile çalışır. (Bir yığın StateT s (ReaderT r IO) gibi, dönüştürülmüş monad'ların sadece kule.)

Ayrıca, altta IO ile büyük bir yığın varsa, tabakaların herhangi bir sayıda bir IO eylemi kaldırmak üzere bir kolaylık işlevi vardır:

liftIO :: (MonadIO m) => IO a -> m a 

Yani IO yılında liftIO (putStrLn "Hello, world!") eserler StateT Int IO, vb ContT r (WriterT [String] IO) ve.

(ek not olarak, foo burada aslında bir fonksiyonu değildir; daha doğru bir terim eylem veya hesaplama içindir.) Eğer hoogle bilmem durumda

+0

Sanırım anlıyorum. Tam olarak açık olmak gerekirse. StateT eklemeden önce bir <- doSomethingInMyMonad 42 yaptığımı düşünün. Şimdi bir <- lift $ doSomethingInMyMonad 42 yapıyorum. Doğru mu? – aelguindy

+0

@aelguindy: Evet! Eğer sadece "MyMonad" kullanan bir kod bölümünüz varsa, bir bütün bloğu da kaldırabilirsiniz: "$ do ...". – ehird

+0

Teşekkürler! Sorulacak doğru yer olup olmadığından emin değil, ancak kaldırmak için bir eşdeğer var mı, ancak 2 bağımsız değişkenle, lift2? * Aptal soru! * Cevabı buldu – aelguindy