मैं कुछ अलग तरह के राज्यों के साथ राज्य मशीनों के एक परिवार को परिभाषित करने की कोशिश कर रहा हूं। विशेष रूप से, अधिक "जटिल" राज्य मशीनों में राज्य होते हैं जो सरल राज्य मशीनों के राज्यों को मिलाकर बनते हैं।
(यह ऑब्जेक्ट ओरिएंटेड सेटिंग के समान है जहां किसी ऑब्जेक्ट में कई विशेषताएँ होती हैं जो ऑब्जेक्ट भी होती हैं।)
यहाँ एक सरल उदाहरण है कि मैं क्या हासिल करना चाहता हूँ।
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
एक मॉनिटर है जो एम 1 को टोकन खिलाता है, और फिर एम 2 के लिए, और फिर उत्पादन करता हैTrue
यदि दोनों उत्तर सही थे। मैं के राज्य का मॉडल बनाना चाहते हैंm1 `and` m2
के साथCombinedState
ऊपर के बाद से दोनों पर नज़र रखता है की राज्य बनाए रखा जाना चाहिए उदाहरण में।
StateT InnerState m Int
पहले स्थान पर कहाँ मूल्य मिल रहा है outerStateFoo
?
_innerVal <$> get
बसgets _innerVal
(के रूप मेंgets f == liftM f get
, औरliftM
सिर्फfmap
साधुओं के लिए विशेष है)।