name: partial-records version: 0.2.0.0 synopsis: Template haskell utilities for constructing records with default values description: . 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 homepage: https://github.com/mniip/partial-records license: BSD3 license-file: LICENSE author: mniip maintainer: mniip@mniip.com copyright: (C) mniip 2019 category: Data build-type: Simple cabal-version: >=1.10 library exposed-modules: Data.Partial , Data.Partial.TH , Data.Partial.Utils build-depends: base >= 4.10 && <= 4.13 , template-haskell >= 2.12 , transformers >= 0.5 hs-source-dirs: src default-language: Haskell2010