请参阅下面的increment
函数中liftIO
的使用。我有预感,有更好的方法可以使用镜头来处理它。有什么建议吗?
{-# LANGUAGE TemplateHaskell #-}
import Control.Lens
import Control.Monad.IO.Class
import Control.Monad.State
data PersistentCounter = PersistentCounter {
_cValue :: Int,
_cFilename :: FilePath
} deriving Show
makeLenses ''PersistentCounter
increment :: StateT PersistentCounter IO ()
increment = do
t <- cValue <+= 1
f <- use cFilename
liftIO $ writeFile f $ show t
编辑:我认为可能有一种类似于下面的“zoom2”的机制。
increment :: StateT PersistentCounter IO ()
increment = do
t <- cValue <+= 1
zoom2 store
store :: PersistentCounter -> IO ()
store counter =
writeFile (counter^.cFilename) $ show (counter^.cValue)
-- | Invoke a function in the inner monad, and pass the state as
-- a parameter.
zoom2 :: Monad m => (s -> m ()) -> StateT s m ()
zoom2 f = get >>= (\s -> lift (f s)) >> return ()
最佳答案
我之前(几乎)写过很多次zoom2
——我通常称之为getsM
。通用版本看起来像
-- from Control.Monad.State
gets :: MonadState s m => (s -> a) -> m a
getsM :: MonadState s m => (s -> m a) -> m a
getsM f = state $ \s -> (,s) <$> f s
或者,如果您不介意修复特定堆栈
-- from Control.Monad.Trans.State
gets :: Monad m => (s -> a) -> StateT s m a
getsM :: Monad m => (s -> m a) -> StateT s m a
getsM f = StateT $ \s -> (,s) <$> f s
关于haskell - 使用透镜对 StateT 中的内部单子(monad)进行操作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20190722/