Безопасное моделирование реляционных данных в Haskell

Я считаю очень распространенным желание моделировать реляционные данные в моих функциональных программах. Например, при разработке веб-сайта мне может понадобиться следующая структура данных для хранения информации о моих пользователях:

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 может их решить (как обычно), но я бы не хотел изобретать велосипед.

37
задан JHannes 19 June 2012 в 03:18
поделиться