Database records and formlets and optionally populated records can be neatly all represented with the same data type when the fields are all indexed.
class Indexed i a where
type Index i (a :: *)
Like:
data Article i =
Article
{ articleId :: Index i Int
, articleTitle :: Index i String
}
It's surprisingly simple, good at type inferring, and powerful what can be done with this basis.
Most importantly, regular use of pattern matching and field construction/updating still works with Identity
as an index.
instance Indexed Identity a where
type Index Identity a = a
identityArticle :: Article Identity
identityArticle =
Article {articleTitle = "Some article", articleId = ArticleId 123}
reverseTitle :: Article Identity -> String
reverseTitle (Article{articleTitle=title}) = reverse title
See below for a more complete exploration of this idea in the context of formlets and databases.
Please comment on the Gist if you've seen other approaches similar to this, or email me at [email protected].
This approach is different (in databases) to:
- opaleye -- EDIT: does use a similar HKD approach
- persistent
- haskell-relational-record
EDIT Beam uses a similar HKD approach.
It's not row types, but it's something interesting.
Using the generics approach, one can simply go back to the plain "unadorned" record using
to
.