Нормализованная и неизменная модель данных
Как Haskell решает проблему "нормализованной неизменной структуры данных"?
Например, рассмотрим структуру данных, представляющую бывших подружек/парней:
data Man = Man {name ::String, exes::[Woman]}
data Woman = Woman {name :: String, exes::[Man]}
Что произойдет, если Женщина изменит свое имя, и она была с 13 мужчинами? Тогда весь 13 человек должен быть "обновлен" (в смысле Хаскелла) тоже? Чтобы избежать этих "обновлений", необходима некоторая нормализация.
Это очень простой пример, но представьте себе модель с 20 сущностями и произвольные отношения между ними, что делать дальше?
Каков рекомендуемый способ представления сложных, нормализованных данных на неизменяемом языке?
Например, решение Scala можно найти здесь (см. код ниже) и использует ссылки. Что делать в Haskell?
class RefTo[V](val target: ModelRO[V], val updated: V => AnyRef) {
def apply() = target()
}
Интересно, если в Haskell не работают более общие решения, такие как выше (в Scala), или они не нужны? Если они не работают, то почему бы и нет? Я попытался найти библиотеки, которые делают это в Haskell, но они, похоже, не существуют.
Другими словами, если я хочу моделировать нормализованную базу данных SQL в Haskell (например, для использования с acid-state), существует общий способ описания внешних ключей? Под общим я имею в виду, а не вручную кодирование идентификаторов, как предложено chepner в комментариях ниже.
EDIT:
Иными словами, существует ли библиотека (для Haskell или Scala), которая реализует SQL/реляционную базу данных в памяти (возможно, также используя Event Sourcing for persistence), так что база данных является неизменной и большинство операций SQL (query/join/insert/delete/etc.) реализованы и безопасны по типу? Если такой библиотеки нет, почему бы и нет? Кажется, это довольно хорошая идея. Как создать такую библиотеку?
ИЗМЕНИТЬ 2:
Некоторые связанные ссылки:
Ответы
Ответ 1
Проблема заключается в том, что вы храните данные и отношения одного типа. Чтобы нормализовать, вам нужно отделить. Реляционные базы данных 101.
newtype Id a = Id Int -- Type-safe ID.
data Person = Person { id :: Id Person, name :: String }
data Ex = Ex { personId :: Id Person, exId :: Id Person }
Теперь, если человек меняет свое имя, влияет только одно значение Person
. Записи Ex
не заботятся о именах людей.
Ответ 2
Проект M63 выглядит довольно закрыть, чтобы Я искал. Это написано в Haskell.
Более легкое решение Haskell изложено в сообщении Gabriel Gonzalez "Очень общий API для реляционных объединений ".