Devlet bir monad ile evleniyor
Üzerinde çalışıyorum bir Haskell proje içerir bağlayan bir büyük düğüm: ben bir ayrıştırma seri temsili bir grafik, her düğüm bazı ofset dosyayı ve başvuru başka bir düğüm tarafından ofset. Kendimi geri besleme sağlayan ayrıştırma sırasında bezlerine uzaklıklar bir harita oluşturmak için do rec
blok ihtiyacım var.
Çalışma var bu, ve biraz-biraz-oldukça StateT
-vari bir monad transformer içine çekilen:
{-# LANGUAGE DoRec, GeneralizedNewtypeDeriving #-}
import qualified Control.Monad.State as S
data Knot s = Knot { past :: s, future :: s }
newtype RecStateT s m a = RecStateT (S.StateT (Knot s) m a) deriving
( Alternative
, Applicative
, Functor
, Monad
, MonadCont
, MonadError e
, MonadFix
, MonadIO
, MonadPlus
, MonadReader r
, MonadTrans
, MonadWriter w )
runRecStateT :: RecStateT s m a -> Knot s -> m (a, Knot s)
runRecStateT (RecStateT st) = S.runStateT st
tie :: MonadFix m => RecStateT s m a -> s -> m (a, s)
tie m s = do
rec (a, Knot s' _) <- runRecStateT m (Knot s s')
return (a, s')
get :: Monad m => RecStateT s m (Knot s)
get = RecStateT S.get
put :: Monad m => s -> RecStateT s m ()
put s = RecStateT $ S.modify $ \ ~(Knot _ s') -> Knot s s'
tie
işlevi sihrin gerçekleştiği yer: 7* *Ara bir değer ve ben de kendi geleceği olarak besleyen bir devlet üretir. get
geçmişin ve geleceğin Birleşik Devletleri hem de okuyabilir, ama put
sadece "mevcut." değiştirmek için izin verdiğini unutmayın
Soru 1Bu uygulamak için iyi bir yol gibi düğüm-ipe genel olarak desen görünüyor mu? Ya da daha iyisi, birileri buna genel bir çözüm hayata geçirdi, Hackage karıştıran zaman gözden kaçırmışım? Muhtemelen daha şık göründüğü için bir süre Cont
monad karşı başımı yendi, (Dan Burton similar post), ama beceremedim.
Tamamen öznel bir Soru 2: Tamamen arama kodunu arayan bulur yolu ile mutlu değilim:
do
Knot past future <- get
let {- ... -} = past
{- ... -} = future
node = {- ... -}
put $ {- ... -}
return node
Uygulama ayrıntıları besbelli ki, burada önemli nokta past
future
devlet almam sahip olmak,-maç desen onları ihmaliçinde bir bağlama yapalım(ya da açıkça önceki desen tembel olun) önemsiyorum ne olursa olsun özü, benim düğüm oluşturmak için, bu devlete, güncelleme ve nihayet düğümü döndürür. Gereksiz yere ayrıntılı görünüyor, ve ben özellikle ne kadar kolay yanlışlıkla past
future
devletler sıkı ayıklayan desen yapmak için sevmemek. Kimse daha iyi bir arayüz olabilirmi?
CEVAP
Uygulanması ile ilgili olarak, Okuyucu bir monad (gelecek için) bir kompozisyon ve Devlet bir monad (geçmiş) hediye edeyim. Sebebi senin geleceğin sadece bir kez (tie
) ayarlayın ve sonra bir değişiklik yok.
{-# LANGUAGE DoRec, GeneralizedNewtypeDeriving #-}
import Control.Monad.State
import Control.Monad.Reader
import Control.Applicative
newtype RecStateT s m a = RecStateT (StateT s (ReaderT s m) a) deriving
( Alternative
, Applicative
, Functor
, Monad
, MonadPlus
)
tie :: MonadFix m => RecStateT s m a -> s -> m (a, s)
tie (RecStateT m) s = do
rec (a, s') <- flip runReaderT s' $ flip runStateT s m
return (a, s')
getPast :: Monad m => RecStateT s m s
getPast = RecStateT get
getFuture :: Monad m => RecStateT s m s
getFuture = RecStateT ask
putPresent :: Monad m => s -> RecStateT s m ()
putPresent = RecStateT . put
İkinci sorunuza gelince, sizin veri akışı bilmek (yani senin için küçük bir kod örneği var) yardımcı olur. Sıkı desenleri her zaman döngüler neden olduğu doğru değil. Üretmeyen bir döngü oluşturmak için dikkatli olmak gerekir bu doğru ama tam olarak ne kısıtlamalar ve bina konum nasıl bağlıdır.
Scalaz devlet monad örnekleri...
Kullanım Haskell devlet kodu bir koku ...
Android izinler: Telefon: oku telefon ...
Nerede Devlet Modeli Angular.js Saklan...
Bir monad nedir?...