Я пишу MUD-сервер в Haskell (MUD = Multi User Dungeon: в основном, многопользовательская текстовая приключенческая/ролевая игра). Данные/состояние игрового мира представлены примерно в 15 различных IntMap s. Модный блок трансформатора выглядит следующим образом: ReaderT MudData IO, где тип MudData - это тип записи, содержащий IntMap s, каждый в своем собственном TVar (я использую STM для concurrency):
data MudData = MudData { _armorTblTVar :: TVar (IntMap Armor)
, _clothingTblTVar :: TVar (IntMap Clothing)
, _coinsTblTVar :: TVar (IntMap Coins)
... и так далее. (Я использую объективы, поэтому подчеркивания.)
Некоторые функции нуждаются в определенных IntMap s, тогда как другим функциям нужны другие. Таким образом, наличие каждого IntMap в своем собственном TVar обеспечивает детализацию.
Однако в моем коде появился шаблон. В функциях, которые обрабатывают команды игроков, мне нужно читать (а иногда и позже писать) на мой TVar в монаде STM. Таким образом, эти функции заканчиваются наличием помощника STM, определенного в их блоках where. У этих помощников STM часто есть несколько операций readTVar, поскольку большинству команд необходимо получить доступ к нескольким IntMap s. Кроме того, функция для данной команды может вызывать несколько чистых вспомогательных функций, которые также нуждаются в некоторых или всех IntMap s. Эти чистые вспомогательные функции, таким образом, иногда приводят к множеству аргументов (иногда более 10).
Итак, мой код стал "замусорен" множеством выражений и функций readTVar, которые принимают большое количество аргументов. Вот мои вопросы: это запах кода? Не хватает ли какой-либо абстракции, которая сделает мой код более элегантным? Есть ли более идеальный способ структурирования моих данных/кода?
Спасибо!