带有fclabels的STM

时间:2015-08-06 16:55:36

标签: haskell concurrency monads stm

我建立了一个小型游戏引擎来管理一块方块(目前用于玩Conway的生活游戏)。所有数据都可以通过fclabels和State的镜头访问。引擎耦合用户输入和图形渲染(通常的游戏循环)。

帧之间的计算有时可能很慢而且执行时间很长。所以我想使用并发来管理方块,使用STM' s TVar

我的数据目前代表如下:

data World = World {
    … -- window configuration, not important
    , _squares :: TVar [Square]
}

mkLabels [''World] -- creates labels, similar to mkLenses

我的功能在Game Monad中运行,定义如下:

type Game a = StateT World IO a

使用monadic versions of labels。我用Getters&我的monad里面的塞特犬。

我想知道是否有办法以某种方式编写行为类似的新标签:

gets :: MonadState f m => Lens (->) f o -> m o 
…
puts :: MonadState f m => Lens (->) f o -> o -> m () 

但是这会照顾STM(get会涉及readTVar,puts会涉及writeTvar等)。

1 个答案:

答案 0 :(得分:3)

如果我理解正确,您需要定义镜头tlens s.t。:

gets tlens

与:

相同
do tvar <- gets squares
   sqs <- liftIO $ atomically $ readTVar tvar
   return sqs

并且puts tlens sqs与:

相同
do tvar <- gets squares
   liftIO $ atomically $ writeTVar tvar sqs 

我认为可以通过查看gets

的类型来回答这个问题
gets :: MonadState f m => Lens (->) f o -> m o

镜头参数是纯粹的而不是一元的。要获得TVar的内容,您需要在IO-monad中运行代码。

此外,Data.Label.Monadic中gets的定义是(link)

gets lens = State.gets (Total.get lens)

其中State是Control.Monad.State,Total是Data.Label.Total。

但是State.gets需要一个纯函数,所以你再也无法创建一个可以与gets一起使用的镜头。