Сегодня на «приключениях в функциональном программировании с объективами» наш герой пытается определить призму над элементом списка, который может или не может существовать.Призмы над элементом существующего списка
Это немного сложно объяснить, поэтому, чтобы избежать проблемы X, Y, я дам фактический прецедент во всей красе.
Я пишу текстовый редактор в Haskell под названием Rasa, вся идея в том, что он чрезвычайно расширяемый, и это означает, что большинство функций написано как расширения. Поскольку это основной принцип, расширения ТАКЖЕ зависят от других расширений, поэтому мне нужен способ централизованного хранения их состояния, чтобы все расширения в зависимости от расширения могли получить доступ к его текущему «состоянию расширения». Конечно, типы этих состояний не известны ядру редактора, поэтому на данный момент я сохраняю список значений Dynamic. Когда расширение хранит состояние он преобразуется в динамическом, то он может быть извлечен позже через призму так:
data Store = Store
{ _event :: [Event]
, _editor :: E.Editor
, _extState :: [Dynamic]
}
ext :: Typeable a => Traversal' Store a
ext = extState.traverse._Dynamic
Так что теперь ext
является полиморфным Traversal, которая по существу работает над только динамикой, что «матч» типа (если вы установите его, он заменит значения одного и того же типа, если вы «получите» от него, он будет действовать как обход по динамике, соответствующий типу исходящего значения). Если это похоже на магию, это в основном ...
BTW, я бы хотел, чтобы в любой момент в списке было точно 1 экземпляр объекта состояния Extension.
Таким образом, получение и настройка на самом деле работают отлично IFF, в списке уже есть нужный тип, мой вопрос: как я могу сделать версию этого обхода таким образом, что если значение соответствующего типа находится в что он заменит его (и будет работать как ожидалось), но это добавит значение в список, если обход будет SET, и в списке нет соответствующего элемента. Я понимаю, что Traversal не должен изменять количество элементов, которые они пересекают, так что, возможно, это должно быть призмой или объективом над самим списком?
Я понимаю, что это действительно сбивает с толку, поэтому, пожалуйста, задать уточняющие вопросы :)
Что касается вещей, которые я принял взглянуть на уже, я смотрел на prefixed и _Cons в качестве возможных способов сделать это, но я «Я просто не совсем уверен, как подключить его. Может быть, я полностью лаем по неправильному дереву.
Я мог бы добавить значение по умолчанию в конец обхода каким-либо образом, но я не хочу требовать моноида или по умолчанию, поэтому я не могу вызвать в воображении элементы из ниоткуда (и я хочу сделать это только тогда, когда SETTING).
Я также открыт для дискуссий о том, действительно ли это правильный способ сохранить это состояние, но это самые изящные решения, которые я нашел до сих пор (хотя я знаю, что при прогнозировании во время выполнения - оптимальный). Я просмотрел тип Vault, но прохождение ключей вокруг не очень хорошо работало, когда я его пробовал (и я думаю, что он имеет похожие проблемы с производительностью при произнесении типов).
Cheers! Спасибо за прочтение.
Похоже, это может сработать! Могли бы вы объяснить (Proxy :: Proxy a)? Создает ли TypeRep для предоставленного типа? Кроме того, мне нужно «принуждение» и «Ext», или я могу сделать «Map TypeRep Dynamic»? или быстрее использует Ext с экзистенциальной квантификацией? (Я полагаю, что unsafeCoerce безопасна, поскольку я знаю, какой тип хранится в typeref). Просто интересно, почему вы сделали выбор, чтобы пойти с «Ext a». Я буду играть с этим, как только у меня будет время, и дайте знать, подходит ли это! –
P.S. Я только хотел, чтобы в любом случае был один из типов Extension, поэтому на самом деле это функция, а не ограничение: D –
Да, это так. Это новый способ получить TypeRep для чего-то. Он был добавлен к базе с 4.7.0.0. Для использования с '(Proxy :: Proxy a)' вам нужно использовать '-XScopedTypeVariables' – freestyle