Bir çeşit farklı devlete sahip bir devlet makineleri ailesi tanımlamaya çalışıyorum. Özellikle, daha "karmaşık" durum makineleri, daha basit durum makinelerinin durumlarının birleştirilmesiyle oluşturulan durumlara sahiptir.
(Bu, bir nesnenin aynı zamanda nesne olan çeşitli özniteliklere sahip olduğu nesne yönelimli bir ayara benzer.)
İşte elde etmek istediğim şeyin basitleştirilmiş bir örneği.
data InnerState = MkInnerState { _innerVal :: Int }
data OuterState = MkOuterState { _outerTrigger :: Bool, _inner :: InnerState }
innerStateFoo :: Monad m => StateT InnerState m Int
innerStateFoo = do
i <- _innerVal <$> get
put $ MkInnerState (i + 1)
return i
outerStateFoo :: Monad m => StateT OuterState m Int
outerStateFoo = do
b <- _outerTrigger <$> get
if b
then
undefined
-- Here I want to "invoke" innerStateFoo
-- which should work/mutate things
-- "as expected" without
-- having to know about the outerState it
-- is wrapped in
else
return 666
Daha genel olarak, bu yuvalamaların daha karmaşık olduğu genelleştirilmiş bir çerçeve istiyorum. İşte nasıl yapılacağını bilmek istediğim bir şey.
class LegalState s
data StateLess
data StateWithTrigger where
StateWithTrigger :: LegalState s => Bool -- if this trigger is `True`, I want to use
-> s -- this state machine
-> StateWithTrigger
data CombinedState where
CombinedState :: LegalState s => [s] -- Here is a list of state machines.
-> CombinedState -- The combinedstate state machine runs each of them
instance LegalState StateLess
instance LegalState StateWithTrigger
instance LegalState CombinedState
liftToTrigger :: Monad m, LegalState s => StateT s m o -> StateT StateWithTrigger m o
liftToCombine :: Monad m, LegalState s => [StateT s m o] -> StateT CombinedState m o
Bağlam için, bu makinelerle elde etmek istediğim şey bu:
Temelde durumsal işlevler olan "Akış Transformatörleri" olarak adlandırılan bu şeyleri tasarlamak istiyorum: Jeton tüketiyorlar, iç durumlarını değiştiriyorlar ve bir şeyler üretiyorlar. Özellikle, çıktı bir Boole değeri olduğu bir Stream Transformers sınıfı ile ilgileniyorum; biz bu "monitör" adını vereceğiz.
Şimdi bu nesneler için birleştiriciler tasarlamaya çalışıyorum. Onlardan bazıları:
- Bir
pre
birleştirici.mon
Bir monitör olduğunu varsayalım . Ardından, ilk belirteç tüketildikten sonrapre mon
her zamanFalse
üretilen ve daha sonramon
önceki belirteç şimdi takılıyormuş gibi davranışı taklit eden bir monitördür . Ben durumunu modellemek isteyeyimpre mon
ileStateWithTrigger
yeni devlet orijinal durumuna birlikte bir boolean olduğundan yukarıdaki örnekte. - Bir
and
birleştirici. Varsayalımm1
vem2
monitörler. Ardından,m1 `and` m2
jetonu m1'e ve sonra m2'ye besleyen veTrue
her iki cevabın da doğru olup olmadığını üreten bir monitördür . I durumunu model istediğinizm1 `and` m2
ileCombinedState
iki monitör durumu muhafaza edilmesi gerektiği için, yukarıdaki örnekte.
StateT InnerState m Int
İlk etapta nereden bir değer elde ediyorsunuz outerStateFoo
?
_innerVal <$> get
sadecegets _innerVal
(gibigets f == liftM f get
veliftM
sadecefmap
monadlar için uzmanlaşmıştır).