Я намагаюся визначити сімейство державних машин з дещо різними видами станів. Зокрема, більш "складні" державні машини мають стани, які утворюються шляхом об'єднання станів більш простих державних машин.
(Це схоже на об'єктно-орієнтовану установку, коли об’єкт має кілька атрибутів, які також є об'єктами.)
Ось спрощений приклад того, що я хочу досягти.
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
Загалом, я хочу узагальнити рамки, де ці гнізда більш складні. Ось я хотів би знати, як це зробити.
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
У контексті цього я хочу досягти завдяки цій техніці:
Я хочу створити ці речі під назвою "Трансформатори потоку", які в основному є функціональними станами: Вони споживають маркер, мутують свій внутрішній стан і щось виводять. Зокрема, мене цікавить клас потокових трансформаторів, де на виході є булеве значення; ми будемо називати цих "моніторів".
Зараз я намагаюся створити комбінатори для цих об’єктів. Деякі з них:
pre
Комбінатор. Припустимо,mon
це монітор. Потім,pre mon
це монітор, який завжди виробляєтьсяFalse
після споживання першого маркера, і потім імітує поведінку так,mon
як ніби вставляється попередній маркер. Я хотів би продемонструвати станpre mon
зStateWithTrigger
у наведеному вище прикладі, оскільки новий стан є булевим разом із початковим станом.and
Комбінатор. Припустимо, що цеm1
іm2
монітори. Потім,m1 `and` m2
це монітор, який подає маркер до m1, а потім до m2, а потім виробляє,True
якщо обидва відповіді були правдивими. Я хотів би, щоб змоделювати станm1 `and` m2
зCombinedState
в наведеному вище прикладі , так як стан обох моніторів повинні бути збережені.
StateT InnerState m Int
цінність в першу чергу outerStateFoo
?
_innerVal <$> get
є справедливимgets _innerVal
(якgets f == liftM f get
, і спеціалізуєтьсяliftM
тількиfmap
на монадах).