Я считаю очень распространенным желание моделировать реляционные данные в моих функциональных программах. Например, при разработке веб-сайта мне может понадобиться следующая структура данных для хранения информации о моих пользователях:
data User = User
{ name :: String
, birthDate :: Date
}
Затем я хочу сохранить данные о сообщениях, которые пользователи публикуют на моем сайте:
data Message = Message
{ user :: User
, timestamp :: Date
, content :: String
}
Есть несколько проблемы, связанные с этой структурой данных:
пользователя
хрупкие - вы можете забыть обновить все вхождения пользователя
в своей структуре данных. С этими проблемами можно справиться, а наши данные можно представить в виде дерева. Например, вы можете выполнить рефакторинг следующим образом:
data User = User
{ name :: String
, birthDate :: Date
, messages :: [(String, Date)] -- you get the idea
}
Тем не менее, ваши данные могут иметь форму DAG (представьте себе любое отношение «многие ко многим») или даже в виде общего графика (хорошо, а может и нет). В этом случае я стараюсь имитировать реляционную базу данных, сохраняя свои данные в Map
s:
newtype Id a = Id Integer
type Table a = Map (Id a) a
Этот вид работает, но небезопасен и уродлив по нескольким причинам:
Id
вызов конструктора вдали от бессмысленных поисков. Может быть
, но часто база данных структурно обеспечивает наличие значения. Есть ли работа по преодолению этих проблем?
Похоже, Template Haskell может их решить (как обычно), но я бы не хотел изобретать велосипед.