Changed description
from
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
to
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