MonadTransControl 是否支持 STM?
Does MonadTransControl support STM?
我正在寻找在 STM.atomically 中使用 monad 转换器的标准方法。
我觉得这听起来很奇怪,因为到目前为止我发现的所有用例都只是 liftIO 。原子地和
直接传递 "STM a" 而不将其包装到任何 monad 转换器中。
我猜,因为原子操作通常不是很复杂 - 只是一个行和
通过局部变量传递参数更容易也更有效,
但在我的情况下交易很大,我想顺利通过主堆栈。
在熟悉了 monad-control 库后,我倾向于发表意见
如果 source 和 result base runInBase 不能解除 monad 堆栈
monad 是不同的,但我不确定。
inNestedState :: MyData -> StateT MyState STM ()
loadCounterA :: MyData -> StateT MyState IO ()
loadCounterA md = do
control $ \runInBase -> atomically (runInBase (inNestedState md))
第一个错误
monad-control-demo.hs:29:4: error:
• Couldn't match type ‘STM’ with ‘IO’
Expected type: StateT MyState IO ()
Actual type: StateT MyState STM ()
• In a stmt of a 'do' block:
control $ \ runInBase -> atomically (runInBase (inNestedState md))
In the expression:
do control
$ \ runInBase -> atomically (runInBase (inNestedState md))
In an equation for ‘loadCounterA’:
loadCounterA md
= do control
$ \ runInBase -> atomically (runInBase (inNestedState md))
|
29 | control $ \runInBase -> atomically (runInBase (inNestedState md))
与此同时,我最终得到了有限但方便的自制解决方案:
class MonadRebase m n where
rebase :: (m a) -> (n a)
instance (MonadRebase m n) => MonadRebase (ReaderT r m) (ReaderT r n) where
rebase t = ReaderT $ \r -> rebase (runReaderT t r)
instance (MonadRebase m n) => MonadRebase (StateT s m) (StateT s n) where
rebase t = StateT $ \s -> rebase (runStateT t s)
instance MonadRebase STM IO where
rebase = atomically
data MyState = MyState {
msCounter1 :: TVar Int,
msCounter2 :: TVar Int,
ops :: Int
}
inStm :: ReaderT Int (StateT MyState STM) ()
inStm = do
rInt <- ask
lift $ do
mySt <- get
modify (\st -> st {ops = rInt + ops st })
lift $ do
c1Val <- (readTVar (msCounter1 mySt))
c2Val <- (readTVar (msCounter2 mySt))
writeTVar (msCounter1 mySt) 0
writeTVar (msCounter2 mySt) (c1Val + c2Val)
foo :: ReaderT Int (StateT MyState IO) ()
foo = do
rebase inStm
任何关于如何对现有库执行相同操作的想法都将受到赞赏。
我将你的问题解释为 "How can I convert a StateT MyState STM ()
to a StateT MyState IO ()
?"。答案是mapStateT
:
loadCounterA = mapStateT atomically . inNestedState
如第二个示例所示,要深入转换器堆栈的多层,只需嵌套转换器各自的 map
函数的应用程序:
foo = mapReaderT (mapStateT atomically) inStm
当你有一个大的转换器堆栈时,这可能有点繁琐,但由于类型检查器,这是一种你不会出错的代码。
我正在寻找在 STM.atomically 中使用 monad 转换器的标准方法。 我觉得这听起来很奇怪,因为到目前为止我发现的所有用例都只是 liftIO 。原子地和 直接传递 "STM a" 而不将其包装到任何 monad 转换器中。 我猜,因为原子操作通常不是很复杂 - 只是一个行和 通过局部变量传递参数更容易也更有效, 但在我的情况下交易很大,我想顺利通过主堆栈。
在熟悉了 monad-control 库后,我倾向于发表意见 如果 source 和 result base runInBase 不能解除 monad 堆栈 monad 是不同的,但我不确定。
inNestedState :: MyData -> StateT MyState STM ()
loadCounterA :: MyData -> StateT MyState IO ()
loadCounterA md = do
control $ \runInBase -> atomically (runInBase (inNestedState md))
第一个错误
monad-control-demo.hs:29:4: error:
• Couldn't match type ‘STM’ with ‘IO’
Expected type: StateT MyState IO ()
Actual type: StateT MyState STM ()
• In a stmt of a 'do' block:
control $ \ runInBase -> atomically (runInBase (inNestedState md))
In the expression:
do control
$ \ runInBase -> atomically (runInBase (inNestedState md))
In an equation for ‘loadCounterA’:
loadCounterA md
= do control
$ \ runInBase -> atomically (runInBase (inNestedState md))
|
29 | control $ \runInBase -> atomically (runInBase (inNestedState md))
与此同时,我最终得到了有限但方便的自制解决方案:
class MonadRebase m n where
rebase :: (m a) -> (n a)
instance (MonadRebase m n) => MonadRebase (ReaderT r m) (ReaderT r n) where
rebase t = ReaderT $ \r -> rebase (runReaderT t r)
instance (MonadRebase m n) => MonadRebase (StateT s m) (StateT s n) where
rebase t = StateT $ \s -> rebase (runStateT t s)
instance MonadRebase STM IO where
rebase = atomically
data MyState = MyState {
msCounter1 :: TVar Int,
msCounter2 :: TVar Int,
ops :: Int
}
inStm :: ReaderT Int (StateT MyState STM) ()
inStm = do
rInt <- ask
lift $ do
mySt <- get
modify (\st -> st {ops = rInt + ops st })
lift $ do
c1Val <- (readTVar (msCounter1 mySt))
c2Val <- (readTVar (msCounter2 mySt))
writeTVar (msCounter1 mySt) 0
writeTVar (msCounter2 mySt) (c1Val + c2Val)
foo :: ReaderT Int (StateT MyState IO) ()
foo = do
rebase inStm
任何关于如何对现有库执行相同操作的想法都将受到赞赏。
我将你的问题解释为 "How can I convert a StateT MyState STM ()
to a StateT MyState IO ()
?"。答案是mapStateT
:
loadCounterA = mapStateT atomically . inNestedState
如第二个示例所示,要深入转换器堆栈的多层,只需嵌套转换器各自的 map
函数的应用程序:
foo = mapReaderT (mapStateT atomically) inStm
当你有一个大的转换器堆栈时,这可能有点繁琐,但由于类型检查器,这是一种你不会出错的代码。