ฉันกำลังพยายามกำหนดตระกูลของเครื่องสถานะที่มีสถานะแตกต่างกันบ้าง โดยเฉพาะอย่างยิ่งยิ่งเครื่องจักรซับซ้อน "รัฐ" มีสถานะที่เกิดขึ้นจากการรวมรัฐของเครื่องจักรรัฐง่ายขึ้น
(สิ่งนี้คล้ายกับการตั้งค่าวัตถุที่วัตถุมีหลายคุณลักษณะที่เป็นวัตถุด้วย)
นี่คือตัวอย่างที่เรียบง่ายของสิ่งที่ฉันต้องการบรรลุ
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
สำหรับบริบทนี่คือสิ่งที่ฉันต้องการบรรลุด้วยเครื่องจักรนี้:
ฉันต้องการออกแบบสิ่งเหล่านี้เรียกว่า "สตรีม Transformers" ซึ่งโดยทั่วไปแล้วเป็นหน้าที่ของรัฐ: พวกเขาใช้โทเค็นเปลี่ยนสถานะภายในและส่งออกบางอย่าง โดยเฉพาะฉันสนใจในคลาสของ Stream Transformers ที่เอาต์พุตเป็นค่าบูลีน เราจะเรียก "จอภาพ" เหล่านี้
ตอนนี้ฉันพยายามออกแบบ combinators สำหรับวัตถุเหล่านี้ บางส่วนของพวกเขาคือ:
- เครื่องคอม
preบิเนเตอร์ สมมติว่าmonเป็นจอภาพ จากนั้นpre monเป็นจอมอนิเตอร์ที่สร้างเสมอFalseหลังจากที่โทเค็นแรกถูกใช้ไปแล้วจะเลียนแบบพฤติกรรมของmonราวกับว่าโทเค็นก่อนหน้านี้ถูกแทรกอยู่ตอนนี้ ฉันต้องการสร้างแบบจำลองสถานะpre monด้วยStateWithTriggerในตัวอย่างข้างต้นเนื่องจากสถานะใหม่เป็นบูลีนพร้อมกับสถานะดั้งเดิม andCombinator สมมติว่า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ความเชี่ยวชาญในการ monads)