Setup:Обновление элементов нескольких коллекций с динамическими функциями
У меня есть несколько коллекций различных структур данных ведьмы представляет состояние моделируемых объектов в виртуальной системе. У меня также есть ряд функций, которые преобразуют (то есть создают новую копию объекта на основе исходного и 0 или более параметров) этих объектов.
Цель состоит в том, чтобы позволить пользователю выбрать какой-либо объект для применения преобразований к (в рамках правил моделирования), применить эти функции к этим объектам и обновить коллекции, заменив старые объекты новыми.
Я хотел бы иметь возможность создавать функцию этого типа, объединяя меньшие преобразования в более крупные. Затем оцените эту комбинированную функцию.
Вопросы:
Как я структурировать свою программу, чтобы сделать это возможным?
Какой комбинатор я использую для создания такой транзакции?
Идеи:
- Поместите все коллекции в одну огромную структуру и передает эту структуру вокруг.
- Используйте состояние монады для выполнения в основном одно и то же
- Используйте IORef (или один из его более мощных кузенов как MVar) и создать действие ввода-вывода
- Использование функционального Реактивное программирует Framework
1 и 2, похоже, что они несут много багажа, особенно если я предполагаю, что в конце концов некоторые коллекции будут внесены в базу данных. (Darn IO Monad)
3, похоже, хорошо работает, но начинает много напоминать воссоздание ООП. Я также не уверен, на каком уровне использовать IORef. (Например IORef (Collection Obj)
или Collection (IORef Obj)
или data Obj {field::IORef(Type)}
)
4 чувствует самый функциональный стиль, но он также, кажется, создает много сложностей коды без большого выигрыша в выразительности.
Пример
У меня есть веб-витрину. Я держу коллекцию продуктов с (помимо прочего) количеством на складе и ценой. У меня также есть коллекция пользователей, имеющих кредит в магазине.
Пользователь приходит и выбирает 3 продукта для покупки и отправляется на регистрацию, используя кредит в магазине. Мне нужно создать новую коллекцию продуктов, у которой есть запас на складе для 3 продуктов, создать новую коллекцию пользователей с дебетовой учетной записью пользователя.
Это означает, что я получаю следующее:
checkout :: Cart -> ProductsCol -> UserCol -> (ProductsCol, UserCol)
Но тогда жизнь становится более сложным, и мне нужно, чтобы иметь дело с налогами:
checkout :: Cart -> ProductsCol -> UserCol -> TaxCol
-> (ProductsCol, UserCol, TaxCol)
И тогда я должен быть уверен, чтобы добавить заказ в очереди доставки:
checkout :: Cart
-> ProductsCol
-> UserCol
-> TaxCol
-> ShipList
-> (ProductsCol, UserCol, TaxCol, ShipList)
И так далее ...
Что я хотел бы написать что-то вроде
checkout = updateStockAmount <*> applyUserCredit <*> payTaxes <*> shipProducts
applyUserCredit = debitUser <*> creditBalanceSheet
но тип-шашка бы пойти апоплексический на меня. Как структурировать это хранилище таким образом, чтобы функции checkout
или applyUserCredit
оставались модульными и абстрактными? Я не могу быть единственным, у кого есть эта проблема, не так ли?
Просто для того, чтобы быть ясным: у вас есть множество функций с типами, похожими на 'A -> A', для разных типов' A'; вы хотите объединить их в составные действия, обновив какое-то общее состояние; и вы не хотите, чтобы каждая функция знала все остальное, что находится в общем состоянии? –
C.A.McCann: Правильно; хотя некоторые из них, возможно, должны быть получены из чего-то типа «B -> A -> A» путем их каррирования. –