如何在State monad中更新州的部分地区?

时间:2018-07-13 22:58:56

标签: haskell monads lens state-monad

我有一种类型想用作状态monad的一部分:

{-# LANGUAGE TemplateHaskell #-}
import Control.Lens

data SomeState = SomeState
  { _int :: Int,
    _string :: String }
makeLenses ''SomeState

我具有对SomeState中的部分状态进行操作的函数。假设他们还使用状态monad:

updateInt :: Int -> State Int ()
updateString :: String -> State String ()

在顶层,我有一个处理整个SomeState的函数。

updateSomeState :: Int -> State SomeState ()

我想将updateIntupdateString称为updateSomeState的一部分。我觉得应该可以使用lense将SomeState状态单子“转换”为其中一部分的状态单子,但我不知道如何。

感谢您的帮助。

1 个答案:

答案 0 :(得分:1)

我相信您可以使用zoom中的Control.Lens.Zoom组合器来做到这一点:

{-# LANGUAGE TemplateHaskell #-}
import Control.Lens
import Control.Monad.State
data SomeState = SomeState { _int :: Int, _string :: String } deriving (Show)
makeLenses ''SomeState
updateInt :: Int -> State Int ()
updateInt x = id .= x
updateString :: String -> State String ()
updateString x = id .= x

updateSomeState :: Int -> State SomeState ()
updateSomeState x = zoom int (updateInt x)

GHCi:

*Main> runStateT (updateSomeState 5) (SomeState 3 "hi")
 Identity ((),SomeState {_int = 5, _string = "hi"})