haskell mtl/transformers相当于镜头的变焦状态
haskell mtl/transformers equivalent of lens' zooming a state
我正在开发一个基于味噌的网络应用程序,我正在尝试将 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 ()
lens
中的 zoom
很方便,因为它使用 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)
我正在开发一个基于味噌的网络应用程序,我正在尝试将 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 ()
lens
中的 zoom
很方便,因为它使用 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)