Как Haskell решает проблему «нормализованной неизменной структуры данных»?Нормализованная и неизменная модель данных
Например, давайте рассмотрим структуру данных, представляющие бывшие подружек/бойфренд:
data Man = Man {name ::String, exes::[Woman]}
data Woman = Woman {name :: String, exes::[Man]}
Что происходит, если женщина меняет свое имя, и она была с 13 людей? Тогда весь 13 человек должен быть «обновлен» (в смысле Хаскелла) тоже? Чтобы избежать этих «обновлений», необходима какая-то нормализация.
Это очень простой пример, но представьте себе модель с 20 сущностями и произвольные отношения между ними, что делать тогда?
Каков рекомендуемый способ представления сложных нормализованных данных на неизменяемом языке?
Например, решение Scala можно найти here (см. Код ниже), и оно использует ссылки. Что делать в Хаскелле?
class RefTo[V](val target: ModelRO[V], val updated: V => AnyRef) {
def apply() = target()
}
Интересно, если более общие решения, как один из приведенных выше (в Scala) не работают в Haskell или они не нужны? Если они не работают, то почему бы и нет? Я попытался найти библиотеки, которые делают это в Haskell, но они, похоже, не существуют.
Другими словами, если я хочу моделировать нормализованную базу данных SQL в Haskell (например, для использования с acid-state), существует ли общий способ описания внешних ключей? Под общим я имею в виду, а не вручную кодирование идентификаторов, как предложено chepner в комментариях ниже.
EDIT:
Еще другими словами, есть библиотека (для Haskell или Scala), который реализует SQL/реляционных баз данных в памяти (возможно также с помощью Event Sourcing для персистенции) таким образом, что база данных является неизменным и большинство операций SQL (запрос/соединение/вставка/удаление/и т. д.) реализованы и безопасны по типу? Если такой библиотеки нет, почему бы и нет? Кажется, это довольно хорошая идея. Как мне создать такую библиотеку?
EDIT 2:
Некоторые ссылки по теме:
- https://realm.io/news/slug-peter-livesey-managing-consistency-immutable-models/
- https://tonyhb.gitbooks.io/redux-without-profanity/content/normalizer.html
- https://github.com/agentm/project-m36
- https://github.com/scalapenos/stamina
- http://www.haskellforall.com/2014/12/a-very-general-api-for-relational-joins.html
Если у вас есть нормализованные данные, разве у вас нет данных Man = Man {name :: String, exes :: [WomanID]} ', где' womanID' был индексом в истории структуры данных «Женщина» (что-то вроде «Map WomanID Woman»? Если вы измените имя значения «Женщина», это не повлияет на какое-либо значение «Человек», ссылающееся на него, вам нужно только обновить одно значение в «Карта». – chepner
Правильно, данный пример не нормирован. Вопрос в том, существует ли общее решение для создания нормализованных структур данных (что-то, что заботится об обработке идентификаторов и т. д.)? Я имею в виду, что делают Haskellers, когда они хотят создать нормализованные данные? Всегда ли они передают код идентификаторам? Или есть еще какое-то общее решение для этой проблемы? Что вы предложили, это пример ручной кодировки идентификаторов, но это может быть автоматизировано, я думаю. Интересно, какое общее решение для создания и резол Эти идентификаторы. – jhegedus
@jhegedus Вопрос в его нынешнем виде немного широк - это действительно зависит от ситуации. Если вы постоянно обновляете мужчин и женщин, вы можете выполнить вычисления в государственной монаде (государство - таблица/карта мужчин/женщин). Если вы ищете функциональный подход к более общим структурам графов, проверьте ['fgl'] (https://hackage.haskell.org/package/fgl). Что касается идентификаторов: есть ситуации, когда вы можете [связать узел] (https://wiki.haskell.org/Tying_the_Knot) (иногда даже используя «карту»), но в целом вам может потребоваться передать идентификаторы кода , – Alec