我正在研究基于味o的Web应用程序,并且试图将Transition Action InnerModel ()
的模型(状态)包装到Transition Action ModelWrapper ()
中,其中
type Miso.Transition action model = StateT model (Writer [Sub action])
和data ModelWrapper = ClientModel Clients.Model | ...
不幸的是,我似乎找不到改变状态类型的方法,或者根本不确定我该怎么做。
documentation显示了如何处理镜头库。到目前为止,我已经将.=
之类的内容改编成Control.Monad.State.modify
,但找不到与zoom
等效的东西,我需要用它来运行未包装模型作为状态的计算。
我尝试了以下所有方法,但没有走运。我最接近的是execStateT,但是我无法保持操作,所以它没用。
下面的代码有不同的尝试来解决它,并且可能会提供一些上下文。
updateModel ::
Action ->
Transition Action ModelWrapper ()
updateModel ac = case ac of
--ShowSection sect -> modify $ \mo -> mo{currentSection=sect}
--UpdateSubmodel submo -> modify $ \mo -> mo{sectionModel=submo}
UpdateSubmodel submo -> put submo
SectionAct sact -> case sact of
ActionClients clac -> do
gets $ \(ModelClients mo) -> mo
(Clients.updateModel sectionPipeback clac)
--return ()
--gets (\(ModelClients mo) -> mo)
--modify ModelClients
--modify $ \mo -> ModelClients mo
--ModelClients mo <- get
--let trans = (Clients.updateModel sectionPipeback clac)
-- w = execStateT trans mo
--put $ ModelClients mo
--let (clmo, acts) = runWriter $ execStateT trans mo
--let w = execStateT trans mo
--StateT (ModelClients $ execWriter w) w ()
--StateT (\ins -> writer )
--execStateT trans mo
--execStateT trans mo
--let (clmo, acts) = runWriter $ execStateT trans mo
--clmo <- lift $ execStateT trans mo
--put $ ModelClients clmo
--lift $ acts
--pure acts
--pure $ SeictionAct a
NoOp -> return ()
答案 0 :(得分:1)
zoom
中的 lens
很方便,因为它使用lens
来同时捕获一个getter和setter。但是,如果没有lens
,则可以显式处理getter和setter并执行相同的操作。添加导入:
import Control.Monad.Trans.Class
import Control.Monad.Trans.State.Strict
然后,您可以实现类似zoom
的功能:
zoomy
:: Monad m
=> (outer -> inner) -- ^ getter
-> (inner -> outer -> outer) -- ^ setter
-> StateT inner m a
-> StateT outer m a
zoomy getter setter action = do
origOuter <- get
(a, newInner) <- lift $ runStateT action (getter origOuter)
let newOuter = setter newInner origOuter
put newOuter
pure a
或者,如果您想直接与数据构造函数一起玩:
zoomier
:: Monad m
=> (outer -> inner) -- ^ getter
-> (inner -> outer -> outer) -- ^ setter
-> StateT inner m a
-> StateT outer m a
zoomier getter setter (StateT action) = StateT $ \origOuter -> do
(a, newInner) <- action (getter origOuter)
let newOuter = setter newInner origOuter
pure (a, newOuter)