partial-records: Template haskell utilities for constructing records with default values
If you have a datatype with a lot of default-able fields, e.g.
data Foo = { fld1 :: Maybe Int , fld2 :: Maybe Char , fld3 :: Word }
and you want to avoid the the boilerplate of writing all the default values every time you construct a record of this type, you could write a "default value" of this type:
defaultFoo :: Foo defaultFoo = Foo { fld1 = Nothing, fld2 = Nothing, fld3 = 0 }
You could then use record modification syntax to make necessary changes to this value. But perhaps you can't / don't want to provide default values for all of the fields, but only some of them? You could implement a "default smart constructor" that would take the non-optional arguments and then fill in the optional ones like so:
defaultFoo :: Word -> Foo defaultFoo x = Foo { fld1 = Nothing, fld2 = Nothing, fld3 = x }
But then you lose the benefit of record syntax: you can't name the fields you're providing values for.
This package reconciles the two problems: with only a little bit of Template Haskell it provides a way to construct a record with optional fields while also letting you refer to the names of those fields. You make two splices:
mkToPartial ''Foo -- defines 'mkfld1', 'mkfld2', 'mkfld3' mkFromPartial "mkFoo" [t|Foo|] [|Foo { fld1 = Nothing, fld2 = Nothing } |] -- defines 'mkFoo'
And then you can use them like so:
val :: Foo val = mkFoo $ mkfld3 123 ? mkfld1 (Just 456) -- val = Foo { fld1 = Just 456, fld2 = Nothing, fld3 = 123 }
The Template Haskell splice lets you define default values for a subset of the
fields, and those defaults will be used when you call mkFoo
. You can list
fields in any order, but if you omit a mandatory field (one that doesn't have
a default), that would be a type error at compile time.
You can make multiple Data.Partial.TH.mkFromPartial
splices, this is
occasionally useful for parameterized types, for example:
data Bar a = { bar1 :: Maybe Int , bar2 :: a } mkToPartial ''Bar mkFromPartial "mkBar" [t|forall a. Bar a|] [|Bar { bar1 = Nothing } |] -- mkBar :: ... -> Bar a, and bar2 is a required field mkFromPartial "mkBarMaybe" [t|forall a. Bar (Maybe a)|] [|Bar { bar1 = Nothing, bar2 = Nothing } |] -- mkBarMaybe :: ... -> Bar (Maybe a), and bar2 is an optional field
Downloads
- partial-records-0.2.2.1.tar.gz [browse] (Cabal source package)
- Package description (as included in the package)
Maintainer's Corner
For package maintainers and hackage trustees
Candidates
Versions [RSS] | 0.1.0.0, 0.2.0.0, 0.2.1.0, 0.2.2.0, 0.2.2.1 |
---|---|
Dependencies | base (>=4.9 && <=4.13), template-haskell (>=2.11), transformers (>=0.5) [details] |
License | BSD-3-Clause |
Copyright | (C) mniip 2019 |
Author | mniip |
Maintainer | mniip@mniip.com |
Category | Data |
Home page | https://github.com/mniip/partial-records |
Uploaded | by mniip at 2019-10-22T17:46:32Z |
Distributions | |
Downloads | 1833 total (5 in the last 30 days) |
Rating | (no votes yet) [estimated by Bayesian average] |
Your Rating | |
Status | Docs available [build log] Last success reported on 2019-10-22 [all 1 reports] |