MyNixOS website logo
Description

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
Metadata

Version

0.2.2.1

Platforms (75)

    Darwin
    FreeBSD
    Genode
    GHCJS
    Linux
    MMIXware
    NetBSD
    none
    OpenBSD
    Redox
    Solaris
    WASI
    Windows
Show all
  • aarch64-darwin
  • aarch64-genode
  • aarch64-linux
  • aarch64-netbsd
  • aarch64-none
  • aarch64_be-none
  • arm-none
  • armv5tel-linux
  • armv6l-linux
  • armv6l-netbsd
  • armv6l-none
  • armv7a-darwin
  • armv7a-linux
  • armv7a-netbsd
  • armv7l-linux
  • armv7l-netbsd
  • avr-none
  • i686-cygwin
  • i686-darwin
  • i686-freebsd
  • i686-genode
  • i686-linux
  • i686-netbsd
  • i686-none
  • i686-openbsd
  • i686-windows
  • javascript-ghcjs
  • loongarch64-linux
  • m68k-linux
  • m68k-netbsd
  • m68k-none
  • microblaze-linux
  • microblaze-none
  • microblazeel-linux
  • microblazeel-none
  • mips-linux
  • mips-none
  • mips64-linux
  • mips64-none
  • mips64el-linux
  • mipsel-linux
  • mipsel-netbsd
  • mmix-mmixware
  • msp430-none
  • or1k-none
  • powerpc-netbsd
  • powerpc-none
  • powerpc64-linux
  • powerpc64le-linux
  • powerpcle-none
  • riscv32-linux
  • riscv32-netbsd
  • riscv32-none
  • riscv64-linux
  • riscv64-netbsd
  • riscv64-none
  • rx-none
  • s390-linux
  • s390-none
  • s390x-linux
  • s390x-none
  • vc4-none
  • wasm32-wasi
  • wasm64-wasi
  • x86_64-cygwin
  • x86_64-darwin
  • x86_64-freebsd
  • x86_64-genode
  • x86_64-linux
  • x86_64-netbsd
  • x86_64-none
  • x86_64-openbsd
  • x86_64-redox
  • x86_64-solaris
  • x86_64-windows