There are typed query libraries, like esqueleto which give you well typed and flexible query semantics, my complaint with it is that it just returns a tuple of lists, with a separate list for each type, you cannot return the data structured in a tree.
So if you have a companies table joined to a contacts table, you'd get a two element tuple with a list of companies and a list of contacts, and then you have to iterate to do the joins and turn it into a JSON tree.
And there is no help at all for wanting to take in a tree of JSON data, and turn it into updates to existing records and inserts for new records.
You could have a library that to knows how to return a tree if you define a typeclass for the tree, but the only way I'd know to do it would be a separate tree data type for each result set. In Ecto you do have to define a structure that knows all the possible associations, but which associations you actually load in any given query is flexible, you can have associations that are not loaded eagerly for one query, and loaded eagerly in another. In Haskell I can't imagine doing that without two different tree structs, because there is nothing that would know how to take two differently typed result sets and make the same tree partially loaded.
> So if you have a companies table joined to a contacts table, you'd get a two element tuple with a list of companies and a list of contacts, and then you have to iterate to do the joins and turn it into a JSON tree.
Esqueleto has a function to avoid n+1's and return a map now:
So if you have a companies table joined to a contacts table, you'd get a two element tuple with a list of companies and a list of contacts, and then you have to iterate to do the joins and turn it into a JSON tree.
And there is no help at all for wanting to take in a tree of JSON data, and turn it into updates to existing records and inserts for new records.
You could have a library that to knows how to return a tree if you define a typeclass for the tree, but the only way I'd know to do it would be a separate tree data type for each result set. In Ecto you do have to define a structure that knows all the possible associations, but which associations you actually load in any given query is flexible, you can have associations that are not loaded eagerly for one query, and loaded eagerly in another. In Haskell I can't imagine doing that without two different tree structs, because there is nothing that would know how to take two differently typed result sets and make the same tree partially loaded.