Haskell的MTL /变压器等效透镜的变焦状态

问题描述 投票:2回答:1

我工作在基于味噌的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 ()
haskell lens
1个回答
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)
© www.soinside.com 2019 - 2024. All rights reserved.