-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | 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
--
@package partial-records
@version 0.2.2.0
-- | 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 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
--
module Data.Partial
-- | Partial T '[b1, b2, ...] is a partial version of the datatype
-- T where the first field's presence is indicated by b1 ::
-- Bool, second field's presence is indicated by b2 and so
-- on. Instances of this would be generated by mkToPartial.
data family Partial (a :: *) :: [Bool] -> *
-- | A "graded semigroup": if we have two partial structures with only some
-- of the fields, we can merge them to obtain a partial structure with
-- the union of the fields. Prefers to take fields from the left hand
-- side. Instances of this would be generated by mkToPartial.
class Graded a
(?) :: Graded a => Partial a b1 -> Partial a b2 -> Partial a (b1 <||> b2)
type family (b1 :: [Bool]) <||> (b2 :: [Bool]) :: [Bool]
-- | Utility functions used by generated Template Haskell code.
module Data.Partial.Utils
data Opt b x
[Has] :: x -> Opt 'True x
[Hasn't] :: Opt 'False x
joinOpt :: Opt b1 x -> Opt b2 x -> Opt (b1 || b2) x
fromOpt :: x -> Opt b x -> x
class Require (dc :: Symbol) (fld :: Symbol) (b :: Bool)
unOpt :: Require dc fld b => p dc -> p fld -> Opt b x -> x
instance Data.Partial.Utils.Require dc fld 'GHC.Types.True
instance (TypeError ...) => Data.Partial.Utils.Require dc fld 'GHC.Types.False
-- | Template Haskell utilities for constructing records with default
-- values.
module Data.Partial.TH
-- | Generate an instance of the Partial family and the
-- Graded class. Takes a data constructor name. For example:
--
--
-- data Foo a = Foo a { fld1 :: Int, fld2 :: a }
-- mkToPartial ''Foo
--
--
-- expands to:
--
--
-- data instance Partial (Foo a) bs where
-- Partial_Foo :: forall a b1 b2.
-- Opt b1 Int -> Opt b2 a -> Partial (Foo a) '[b1, b2]
-- {-# INLINE mkfld1 #-}
-- mkfld1 :: Int -> Partial (Foo a) '[ 'True, 'False]
-- mkfld1 x = Partial_Foo (Has x) Hasn't
-- {-# INLINE mkfld2 #-}
-- mkfld2 :: a -> Partial (Foo a) '[ 'False, 'True]
-- mkfld2 x = Partial_Foo Hasn't (Has x)
-- instance Graded (Foo a) where
-- {-# INLINE (?) #-}
-- Partial_Foo x1 x2 ? Partial_Foo y1 y1
-- = Partial_Foo (joinOpt x1 y1) (joinOpt x2 y2)
--
mkToPartial :: Name -> Q [Dec]
-- | Generate a function that turns a Partial into a value of the
-- actual datatype. Takes a name for the function to be defined, as well
-- as the type the result should have (can include type variables but all
-- of them must be quantified), as well as the "default values": a record
-- construction specifying just those fields that you want, with their
-- default values. For example:
--
--
-- data Foo a = Foo a { fld1 :: Int, fld2 :: a }
-- mkFromPartial "mkFoo" [t|forall a. Foo (Maybe a)|] [|Foo { fld2 = Nothing }|]
--
--
-- expands to:
--
--
-- {-# INLINE mkFoo #-}
-- mkFoo :: forall a b1 b2.
-- ( Require "Foo" "fld1" b1
-- -- ^ Assert that b1 ~ 'True but generate a nice error message if not
-- )
-- => Partial (Foo (Maybe a)) '[b1, b2] -> Foo (Maybe a)
-- mkFoo (Partial_Foo x1 x2) = Foo (unOpt x1) (fromOpt Nothing x2)
--
mkFromPartial :: String -> Q Type -> Q Exp -> Q [Dec]
-- | The default procedure for generating field constructors from field
-- names is prepending "mk". You can override this behavior by
-- passing a custom field name generating function to this function.
mkToPartialWith :: (String -> String) -> Name -> Q [Dec]