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.
I've seen this described as the Higher Kinded Data pattern, where instead of the
Index
associated type, it's defined as:Does your approach have any advantages?