Reputation: 1281
I have a type that I'd like to use as part of a state monad:
{-# LANGUAGE TemplateHaskell #-}
import Control.Lens
data SomeState = SomeState
{ _int :: Int,
_string :: String }
makeLenses ''SomeState
I have functions that operate on parts of the state in SomeState
. Let's say they also use a state monad:
updateInt :: Int -> State Int ()
updateString :: String -> State String ()
On the top-level I have a functions that deal with the whole SomeState
.
updateSomeState :: Int -> State SomeState ()
I would like to call updateInt
and updateString
as part of updateSomeState
. I have the feeling it should be possible to "convert" the SomeState state monad into a state monad for one of its parts using lense, but I fail to see how.
Any help is appreciated.
Upvotes: 1
Views: 368
Reputation: 1590
I believe that you can do this with the zoom
combinator from 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"})
Upvotes: 1