STM с fclabels

Я создал небольшой игровой движок для управления доской из квадратов (в настоящее время используется для игры в жизнь Конвея). Доступ ко всем данным осуществляется через линзы из fclabels и State. Движок объединяет пользовательский ввод и графический рендеринг (обычный игровой цикл).

Вычисления между кадрами иногда могут выполняться медленно и долго. Поэтому я хотел бы использовать параллелизм для управления квадратами, используя STM TVar.

Мои данные в настоящее время представлены следующим образом:

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

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

Мои функции выполняются в игровой монаде, которая определяется следующим образом:

type Game a = StateT World IO a

Использование монадических версий меток. Я использую геттеры и сеттеры внутри своей монады.

Я хотел бы знать, есть ли способ как-то написать новые метки, которые ведут себя следующим образом:

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

Но это заботится о STM (gets будет включать readTVar, puts будет включать writeTvar и т. д.).


person qleguennec    schedule 06.08.2015    source источник
comment
Прежде чем рассматривать параллелизм, вы можете сначала найти свои узкие места. Если вы просто играете в жизнь, вы легко сможете получать несколько сотен обновлений в секунду даже на скромном оборудовании.   -  person Cubic    schedule 06.08.2015
comment
@Cubic игра в жизнь в настоящее время предназначена только для тестирования движка. Это не проблема оптимизации, а возможность обрабатывать входные данные за то же время, что и вычисление игровой механики.   -  person qleguennec    schedule 06.08.2015
comment
@Cubic частота также зависит от размера платы.   -  person qleguennec    schedule 06.08.2015


Ответы (1)


Если я вас правильно понял, вы хотите определить линзу 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-монаде.

Более того, определение gets в Data.Label.Monadic — это (ссылка) это:

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

где Состояние — это Control.Monad.State, а Total — это Data.Label.Total.

Но State.gets выполняет чистую функцию, поэтому опять же вы не сможете создать линзу, которая будет работать с gets.

person ErikR    schedule 06.08.2015
comment
Я знал об этом и думал, что смогу как-то обойти это, используя Data.Label.Point. Он использует стрелки, которые (несколько?) связаны с монадами. Стоит ли мне попробовать, или я просто говорю глупости? Я еще не совсем понимаю точки, но они, безусловно, кажутся расширяемыми. - person qleguennec; 06.08.2015
comment
Взгляните на этот ответ: stackoverflow.com/questions/18794745/ - у него даже есть пример STM. - person ErikR; 06.08.2015