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 Ids 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.