I find it very common to want to model relational data in my functional programs. For example, when developing a web-site I may want to have the following data structure to stor
I don't have a complete solution, but I suggest taking a look at the ixset package; it provides a set type with an arbitrary number of indices that lookups can be performed with. (It's intended to be used with acid-state for persistence.)
You do still need to manually maintain a "primary key" for each table, but you could make it significantly easier in a few ways:
Adding a type parameter to Id
, so that, for instance, a User
contains an Id User
rather than just an Id
. This ensures you don't mix up Id
s for separate types.
Making the Id
type abstract, and offering a safe interface to generating new ones in some context (like a State
monad that keeps track of the relevant IxSet
and the current highest Id
).
Writing wrapper functions that let you, for example, supply a User
where an Id User
is expected in queries, and that enforce invariants (for example, if every Message
holds a key to a valid User
, it could allow you to look up the corresponding User
without handling a Maybe
value; the "unsafety" is contained within this helper function).
As an additional note, you don't actually need a tree structure for regular data types to work, since they can represent arbitrary graphs; however, this makes simple operations like updating a user's name impossible.