Safe Haskell | None |
---|---|
Language | Haskell2010 |
Synopsis
- option :: OptReader a -> OptionOpt '[] a
- optionWith :: OptReader a -> (OptionOpt '[] a -> OptionOpt attr b) -> Opt b
- flag :: a -> a -> FlagOpt '[] a
- flagWith :: a -> a -> (FlagOpt '[] a -> FlagOpt attr b) -> Opt b
- switch :: FlagOpt '[] Bool
- switchWith :: (FlagOpt '[] Bool -> FlagOpt attr Bool) -> Opt Bool
- switch' :: FlagOpt '[] Bool
- switchWith' :: (FlagOpt '[] Bool -> FlagOpt attr Bool) -> Opt Bool
- argument :: OptReader a -> ArgumentOpt '[] a
- argumentWith :: OptReader a -> (ArgumentOpt '[] a -> ArgumentOpt attr b) -> Opt b
- newtype Single (a :: Type) (f :: Type -> Type) = Single {
- getSingle :: f a
- single :: f a -> Single a f
- newtype Nested (b :: Type) (f :: Type -> Type) = Nested (HKD b f)
- nested :: forall b f k. (Build b f k, Coercible (HKD b f) (Nested b f), Coercible k (Nest k f)) => Nest k f
- getNested :: Construct f b => Nested b f -> f b
- data AssocListF (ts :: [Symbol]) (xs :: [(Type -> Type) -> Type]) (f :: Type -> Type) where
- ANil :: AssocListF '[] '[] f
- ACons :: x f -> AssocListF ts xs f -> AssocListF (t ': ts) (x ': xs) f
- type family l :+ r = (res :: (Type -> Type) -> Type) where ...
- pattern (:+) :: x f -> AssocListF ts xs f -> AssocListF (t ': ts) (x ': xs) f
- data (t :: Symbol) :-> (v :: (Type -> Type) -> Type) :: (Type -> Type) -> Type
- data ((a :: (Type -> Type) -> Type) :* (b :: (Type -> Type) -> Type)) (f :: Type -> Type) = (a f) :* (b f)
- newtype Tagged (t :: k) (a :: (Type -> Type) -> Type) (f :: Type -> Type) = Tagged {
- unTagged :: a f
- optLong :: HasLong o attr => String -> o attr a -> o attr a
- optShort :: HasShort o attr => Char -> o attr a -> o attr a
- optHelp :: HasHelp o attr => String -> o attr a -> o attr a
- optMetavar :: HasMetavar o attr => String -> o attr a -> o attr a
- optEnvVar :: HasEnvVar o attr => String -> o attr a -> o attr a
- optDefault :: (HasDefault o attr, NotInAttrs OptOptional attr "optDefault" "optOptional") => a -> o attr a -> o (OptDefault ': attr) a
- optOptional :: (HasOptional o attr, NotInAttrs OptDefault attr "optOptional" "optDefault") => o attr a -> o (OptOptional ': attr) (Maybe a)
- toOpt :: IsOpt o attr => o attr a -> Opt a
- data Opt a
- parseWith :: (String -> Maybe a) -> String -> Either String a
- readParser :: Read a => OptReader a
- strParser :: IsString s => String -> Either String s
- boolParser :: String -> Either String Bool
- execOpt :: forall c a. (TraversableB a, ProductB a, TraversableB c, ProductB c, GetSource c Identity, RunSource (SourceVal c) a) => c Opt -> a Opt -> IO (a Identity)
- execOptDef :: forall a. (TraversableB a, ProductB a) => a Opt -> IO (a Identity)
- execCommands :: forall c ts xs. (TraversableB (VariantF xs), TraversableB c, ProductB c, Subcommands ts xs, GetSource c Identity, All (RunSource (SourceVal c)) xs, All (RunSource ()) xs, MapAssocList xs) => c Opt -> AssocListF ts xs Opt -> IO (VariantF xs Identity)
- execCommandsDef :: forall ts xs. (TraversableB (VariantF xs), Subcommands ts xs, All (RunSource EnvSourceVal) xs, All (RunSource ()) xs, MapAssocList xs) => AssocListF ts xs Opt -> IO (VariantF xs Identity)
- data EnvSource (f :: Type -> Type) = EnvSource
- newtype JSONSource f = JSONSource (f ConfigFile)
- newtype YAMLSource f = YAMLSource (f ConfigFile)
- data ConfigFile
- noSources :: NoSource f
- defaultSources :: EnvSource f
- getCtx :: IO HargCtx
- ctxFromArgs :: Args -> IO HargCtx
- ctxFromEnv :: Environment -> IO HargCtx
- pureCtx :: Environment -> Args -> HargCtx
- data VariantF (xs :: [(Type -> Type) -> Type]) (f :: Type -> Type) where
- fromVariantF :: FromVariantF xs result f => VariantF xs f -> FoldSignatureF xs result f
- pattern In1 :: x1 f -> VariantF (x1 ': xs) f
- pattern In2 :: x2 f -> VariantF (x1 ': (x2 ': xs)) f
- pattern In3 :: x3 f -> VariantF (x1 ': (x2 ': (x3 ': xs))) f
- pattern In4 :: x4 f -> VariantF (x1 ': (x2 ': (x3 ': (x4 ': xs)))) f
- pattern In5 :: x5 f -> VariantF (x1 ': (x2 ': (x3 ': (x4 ': (x5 ': xs))))) f
- class FunctorB (b :: (k -> Type) -> Type)
- class FunctorB b => TraversableB (b :: (k -> Type) -> Type)
- class FunctorB b => ProductB (b :: (k -> Type) -> Type)
- data HKD structure (f :: Type -> Type)
- build :: Build structure f k => k
- construct :: Construct f structure => HKD structure f -> f structure
Summary
harg
is a wrapper around optparse-applicative
that allows blending
command-line configuration with environment variables, defaults as well as
other sources such as JSON or YAML files. Here are some very simple examples:
- Flat configuration type
data Config
= Config
{ host :: String
, port :: Int
, log :: Bool
, dir :: Maybe String
}
-- Using HKD
from higgledy
configOpt :: HKD Config Opt
configOpt
= build @Config hostOpt portOpt logOpt dirOpt
where
hostOpt
= optionWith strParser
( optLong "host"
. optShort 'h'
. optHelp "Hostname"
. optEnvVar "HOST_NAME"
)
portOpt
= optionWith readParser
( optLong "port"
. optShort 'p'
. optHelp "Port number"
. optDefault 5432
)
logOpt
= switchWith
( optLong "log"
. optHelp "Whether to log or not"
)
dirOpt
= argumentWith strParser
( optHelp "Some directory"
. optEnvVar "SOME_DIR"
. optOptional
)
main :: IO Config
main = do
result <- execOpt defaultSources configOpt
pure $ runIdentity (construct result)
The above could also be:
type ConfigOpt = Single String :* Single Int :* Single Bool :* Single String configOpt :: ConfigOpt Opt configOpt = hostOpt :* portOpt :* logOpt :* dirOpt where ... main :: IO Config main = do host :* port :* log :* dir <- execOpt defaultSources configOpt pure $ runIdentity $ Config <$> getSingle host <*> getSingle port <*> getSingle log <*> getSingle dir
- Nested configuration type
data Config
= Config
{ dbConfig :: DbConfig
, serverConfig :: ServerConfig
}
data DbConfig
= DbConfig
{ dbHost :: String
, dbPort :: Int
}
data ServerConfig
= ServerConfig
{ srvPort :: Int
, srvLog :: Bool
}
type ConfigOpt
= HKD DbConfig
:* HKD ServerConfig
configOpt :: ConfigOpt Opt
configOpt
= dbOpt :* srvOpt
where
dbOpt = build DbConfig ...
srvOpt = build
ServerConfig ...
main :: IO Config
main = do
db :* srv <- execOpt defaultSources configOpt
pure
$ runIdentity
$ Config
<$> construct db
<*> construct srv
- Subparsers
data OneConfig = OneConfig ... data OtherConfig = OtherConfig ... data Config = "one" :-> OneConfig :+ "other" :-> OtherConfig configOpt :: Config Opt configOpt = oneOpt :+ otherOpt :+ ANil where oneOpt = ... otherOpt = ... main :: IO () main = do result <- execOpt defaultSources configOpt case result of HereF one -> runWithOne one ThereF (HereF other) -> runWithOther other where runWithOne :: One -> IO () runWithOne = ... runWithOther :: Other -> IO () runWithOther = ...
TODO: more (and better) examples
Option declaration
optionWith :: OptReader a -> (OptionOpt '[] a -> OptionOpt attr b) -> Opt b Source #
:: a | Default value |
-> a | Active value |
-> FlagOpt '[] a |
Create a flag parser, equivalent to option
. The
first argument is the default value (returned when the flag modifier is
absent), and the second is the active value (returned when the flag
modifier is present). The result can then be used with toOpt
to convert
into the global Opt
type.
someFlag :: Opt Int someFlag = toOpt ( flag 0 1 & optLong "someflag" & optHelp "Some flag" )
:: a | Default value |
-> a | Active value |
-> (FlagOpt '[] a -> FlagOpt attr b) | |
-> Opt b |
switch :: FlagOpt '[] Bool Source #
A flag
parser, specialized to Bool
. The parser (e.g. when parsing
an environment variable) will accept true
and false
, but case
insensitive, rather than using the Read
instance for Bool
. The
default value is False
, and the active value is True
.
someSwitch :: Opt Bool someSwitch = toOpt ( switch & optLong "someswitch" & optHelp "Some switch" )
argumentWith :: OptReader a -> (ArgumentOpt '[] a -> ArgumentOpt attr b) -> Opt b Source #
newtype Single (a :: Type) (f :: Type -> Type) Source #
Single a f
is a newtype around f a
, which allows mixing non-nested
with nested values when creating configuration parsers, using
:*
.
data User = User { name :: String, age :: Int } deriving Generic myConfig :: (Nested User :* Single Int) Opt myConfig = nested @User nameOpt ageOpt :* single intOpt where ...
Instances
ProductB (Single a :: (Type -> Type) -> Type) Source # | |
TraversableB (Single a :: (Type -> Type) -> Type) Source # | |
Defined in Options.Harg.Single btraverse :: Applicative t => (forall (a0 :: k). f a0 -> t (g a0)) -> Single a f -> t (Single a g) # | |
FunctorB (Single a :: (Type -> Type) -> Type) Source # | |
Defined in Options.Harg.Single | |
(Show a, Show (f a)) => Show (Single a f) Source # | |
Generic (f a) => Generic (Single a f) Source # | |
FromJSON (f a) => FromJSON (Single a f) Source # | |
type Rep (Single a f) Source # | |
Defined in Options.Harg.Single |
newtype Nested (b :: Type) (f :: Type -> Type) Source #
Newtype wrapper around HKD
.
Instances
ProductB (HKD b) => ProductB (Nested b :: (Type -> Type) -> Type) Source # | |
TraversableB (HKD b) => TraversableB (Nested b :: (Type -> Type) -> Type) Source # | |
Defined in Options.Harg.Nested btraverse :: Applicative t => (forall (a :: k). f a -> t (g a)) -> Nested b f -> t (Nested b g) # | |
FunctorB (HKD b) => FunctorB (Nested b :: (Type -> Type) -> Type) Source # | |
Defined in Options.Harg.Nested | |
Generic (HKD b f) => Generic (Nested b f) Source # | |
FromJSON (HKD b f) => FromJSON (Nested b f) Source # | |
type Rep (Nested b f) Source # | |
Defined in Options.Harg.Nested |
nested :: forall b f k. (Build b f k, Coercible (HKD b f) (Nested b f), Coercible k (Nest k f)) => Nest k f Source #
data AssocListF (ts :: [Symbol]) (xs :: [(Type -> Type) -> Type]) (f :: Type -> Type) where Source #
A heterogeneous list that holds higher-kinded types and the associated
type constructor, along with a type level list of Symbol
s that act
as tags for each type.
ANil :: AssocListF '[] '[] f | |
ACons :: x f -> AssocListF ts xs f -> AssocListF (t ': ts) (x ': xs) f |
type family l :+ r = (res :: (Type -> Type) -> Type) where ... infixr 4 Source #
Helper type-level function to construct an AssocList
which is not
yet applied to the type constructor that needs to be fully applied.
type Config = "run" :-> RunConfig :+ "test" :-> TestConfig
Config
above has type (Type -> Type) -> Type
, and requires a type
like Opt
to be fully applied.
(tl :-> vl) :+ (tr :-> vr) = AssocListF '[tl, tr] '[vl, vr] | |
(tl :-> vl) :+ (AssocListF ts vs) = AssocListF (tl ': ts) (vl ': vs) | |
l :+ r = TypeError (((Text "Invalid type for tagged options. Construct like this:" :$$: Text "type MyConfig") :$$: Text " = \"one\" :-> ConfigForOne") :$$: Text " :+ \"two\" :-> ConfigForTwo") |
pattern (:+) :: x f -> AssocListF ts xs f -> AssocListF (t ': ts) (x ': xs) f infixr 4 Source #
data ((a :: (Type -> Type) -> Type) :* (b :: (Type -> Type) -> Type)) (f :: Type -> Type) infixr 4 Source #
Infix version of Product
. Allows to combine
higher-kinded types, and keep them partially applied until needed:
data User = User { name :: String, age :: Int } deriving Generic type Config = Nested User :* Single Int configOpt :: Config Opt configOpt = ...
(a f) :* (b f) infixr 4 |
Instances
newtype Tagged (t :: k) (a :: (Type -> Type) -> Type) (f :: Type -> Type) Source #
This type adds a type-level phantom tag to a higher-kinded type.
Its JSON instance allows using :*
with JSONSource
.
Instances
ProductB a => ProductB (Tagged t a :: (Type -> Type) -> Type) Source # | |
TraversableB a => TraversableB (Tagged t a :: (Type -> Type) -> Type) Source # | |
Defined in Options.Harg.Het.Prod btraverse :: Applicative t0 => (forall (a0 :: k). f a0 -> t0 (g a0)) -> Tagged t a f -> t0 (Tagged t a g) # | |
FunctorB a => FunctorB (Tagged t a :: (Type -> Type) -> Type) Source # | |
Defined in Options.Harg.Het.Prod | |
(FromJSON (a Maybe), FromJSON (b Maybe), ProductB a, ProductB b, KnownSymbol ta, KnownSymbol tb) => FromJSON ((Tagged ta a :* Tagged tb b) Maybe) Source # | |
(FromJSON (a Maybe), FromJSON (b' Maybe), ProductB a, ProductB b', KnownSymbol ta, b' ~ (Tagged tb b :* c)) => FromJSON ((Tagged ta a :* (Tagged tb b :* c)) Maybe) Source # | |
Generic (Tagged t a f) Source # | |
FromJSON (a f) => FromJSON (Tagged t a f) Source # | |
type Rep (Tagged t a f) Source # | |
Defined in Options.Harg.Het.Prod |
Option modifiers
optLong :: HasLong o attr => String -> o attr a -> o attr a Source #
Add a long
modifier to an option
optShort :: HasShort o attr => Char -> o attr a -> o attr a Source #
Add a short
modifier to an option
optMetavar :: HasMetavar o attr => String -> o attr a -> o attr a Source #
Add a metavar
metavar to an option, to be
displayed as the meta-parameter next to long/short modifiers
optEnvVar :: HasEnvVar o attr => String -> o attr a -> o attr a Source #
Specify an environment variable to lookup for an option
optDefault :: (HasDefault o attr, NotInAttrs OptOptional attr "optDefault" "optOptional") => a -> o attr a -> o (OptDefault ': attr) a Source #
Add a default value to an option. Cannot be used in conjuction with
optOptional
.
optOptional :: (HasOptional o attr, NotInAttrs OptDefault attr "optOptional" "optDefault") => o attr a -> o (OptOptional ': attr) (Maybe a) Source #
Specify that an option is optional. This will convert an Opt a
to an
Opt (Maybe a)
The basic option type
Option parsers
readParser :: Read a => OptReader a Source #
A parser that uses the Read
instance to parse into a type.
strParser :: IsString s => String -> Either String s Source #
A parser that returns a string. Any type that has an instance of
IsString
will work, and this parser always succeeds.
boolParser :: String -> Either String Bool Source #
A parser that returns a Bool
. This will succeed for the strings
true
and false
in a case-insensitive manner.
Executing options
:: (TraversableB a, ProductB a, TraversableB c, ProductB c, GetSource c Identity, RunSource (SourceVal c) a) | |
=> c Opt | Source options |
-> a Opt | Target configuration options |
-> IO (a Identity) |
Run the option parser and combine with values from the specified sources
:: (TraversableB a, ProductB a) | |
=> a Opt | Target configuration options |
-> IO (a Identity) |
Run the option parser only with default sources (environment variables)
:: (TraversableB (VariantF xs), TraversableB c, ProductB c, Subcommands ts xs, GetSource c Identity, All (RunSource (SourceVal c)) xs, All (RunSource ()) xs, MapAssocList xs) | |
=> c Opt | Source options |
-> AssocListF ts xs Opt | Target options associated with subcommands |
-> IO (VariantF xs Identity) |
Run the subcommand parser and combine with values from the specified sources
:: (TraversableB (VariantF xs), Subcommands ts xs, All (RunSource EnvSourceVal) xs, All (RunSource ()) xs, MapAssocList xs) | |
=> AssocListF ts xs Opt | Target options associated with subcommands |
-> IO (VariantF xs Identity) |
Run the subcommand parser only with default sources (environment variables)
Option sources
data EnvSource (f :: Type -> Type) Source #
Source that enables a parser to read options from environment variables.
Instances
Generic (EnvSource f) Source # | |
ProductB EnvSource Source # | |
TraversableB EnvSource Source # | |
Defined in Options.Harg.Sources.Env btraverse :: Applicative t => (forall (a :: k). f a -> t (g a)) -> EnvSource f -> t (EnvSource g) # | |
FunctorB EnvSource Source # | |
Defined in Options.Harg.Sources.Env | |
type Rep (EnvSource f) Source # | |
newtype JSONSource f Source #
Source that enables a parser to read options from a JSON file.
JSONSource (f ConfigFile) |
Instances
newtype YAMLSource f Source #
Source that enables a parser to read options from a YAML file.
YAMLSource (f ConfigFile) |
Instances
data ConfigFile Source #
This type describes configuration files, for use with e.g. the JSON
source. The reason to not use FilePath
directly is that the user might
prefer to do nothing if the option for the config file has not been not
provided, and there's no default. Because this type has an IsString
instance, it's very easy to define an option. For example, to define a json
source with a default value:
srcOpt :: JSONSource Opt srcOpt = JSONSource jsonOpt where jsonOpt = optionWith strParser ( optLong "json-config" . optDefault (ConfigFile "~/config.json") )
And an optional JSON source:
srcOpt :: JSONSource Opt srcOpt = JSONSource jsonOpt where jsonOpt = optionWith strParser ( optLong "json-config" . optDefault NoConfigFile )
Instances
IsString ConfigFile Source # | |
Defined in Options.Harg.Sources.Types fromString :: String -> ConfigFile # |
defaultSources :: EnvSource f Source #
Default sources, equivalent to EnvSource
Parser context
ctxFromArgs :: Args -> IO HargCtx Source #
ctxFromEnv :: Environment -> IO HargCtx Source #
Variant
data VariantF (xs :: [(Type -> Type) -> Type]) (f :: Type -> Type) where Source #
A Variant is similar to nested Either
s. For example, Variant '[Int,
Bool, Char]
is isomorphic to Either Int (Either Bool Char)
. VariantF
is a variant for higher-kinded types, which means that the type-level list
holds types of kind (Type -> Type) -> Type
, and the second parameter is
the type constructor f :: Type -> Type
. To pattern match on a variant,
HereF
and ThereF
can be used:
getFromVariant :: Variant '[Int, Bool, String] -> Bool getFromVariant (ThereF (HereF b)) = b
Instances
(TraversableB x, TraversableB (VariantF xs)) => TraversableB (VariantF (x ': xs) :: (Type -> Type) -> Type) Source # | |
Defined in Options.Harg.Het.Variant btraverse :: Applicative t => (forall (a :: k). f a -> t (g a)) -> VariantF (x ': xs) f -> t (VariantF (x ': xs) g) # | |
TraversableB (VariantF ([] :: [(Type -> Type) -> Type])) Source # | |
Defined in Options.Harg.Het.Variant btraverse :: Applicative t => (forall (a :: k). f a -> t (g a)) -> VariantF [] f -> t (VariantF [] g) # | |
(FunctorB x, FunctorB (VariantF xs)) => FunctorB (VariantF (x ': xs) :: (Type -> Type) -> Type) Source # | |
Defined in Options.Harg.Het.Variant | |
FunctorB (VariantF ([] :: [(Type -> Type) -> Type])) Source # | |
Defined in Options.Harg.Het.Variant |
fromVariantF :: FromVariantF xs result f => VariantF xs f -> FoldSignatureF xs result f Source #
Re-exports
class FunctorB (b :: (k -> Type) -> Type) #
Barbie-types that can be mapped over. Instances of FunctorB
should
satisfy the following laws:
bmap
id
=id
bmap
f .bmap
g =bmap
(f . g)
There is a default bmap
implementation for Generic
types, so
instances can derived automatically.
Instances
class FunctorB b => TraversableB (b :: (k -> Type) -> Type) #
Barbie-types that can be traversed from left to right. Instances should satisfy the following laws:
t .btraverse
f =btraverse
(t . f) -- naturalitybtraverse
Identity
=Identity
-- identitybtraverse
(Compose
.fmap
g . f) =Compose
.fmap
(btraverse
g) .btraverse
f -- composition
There is a default btraverse
implementation for Generic
types, so
instances can derived automatically.
Instances
(FunctorB (HKD structure), GTraversableB (Rep structure)) => TraversableB (HKD structure :: (Type -> Type) -> Type) | |
Defined in Data.Generic.HKD.Types btraverse :: Applicative t => (forall (a :: k). f a -> t (g a)) -> HKD structure f -> t (HKD structure g) # | |
(TraversableB x, TraversableB (VariantF xs)) => TraversableB (VariantF (x ': xs) :: (Type -> Type) -> Type) Source # | |
Defined in Options.Harg.Het.Variant btraverse :: Applicative t => (forall (a :: k). f a -> t (g a)) -> VariantF (x ': xs) f -> t (VariantF (x ': xs) g) # | |
TraversableB (VariantF ([] :: [(Type -> Type) -> Type])) Source # | |
Defined in Options.Harg.Het.Variant btraverse :: Applicative t => (forall (a :: k). f a -> t (g a)) -> VariantF [] f -> t (VariantF [] g) # | |
TraversableB (HKD b) => TraversableB (Nested b :: (Type -> Type) -> Type) Source # | |
Defined in Options.Harg.Nested btraverse :: Applicative t => (forall (a :: k). f a -> t (g a)) -> Nested b f -> t (Nested b g) # | |
TraversableB (Single a :: (Type -> Type) -> Type) Source # | |
Defined in Options.Harg.Single btraverse :: Applicative t => (forall (a0 :: k). f a0 -> t (g a0)) -> Single a f -> t (Single a g) # | |
TraversableB (Proxy :: (k -> Type) -> Type) | |
Defined in Data.Barbie.Internal.Traversable btraverse :: Applicative t => (forall (a :: k0). f a -> t (g a)) -> Proxy f -> t (Proxy g) # | |
TraversableB (Void :: (k -> Type) -> Type) | |
Defined in Data.Barbie.Trivial btraverse :: Applicative t => (forall (a :: k0). f a -> t (g a)) -> Void f -> t (Void g) # | |
TraversableB (Unit :: (k -> Type) -> Type) | |
Defined in Data.Barbie.Trivial btraverse :: Applicative t => (forall (a :: k0). f a -> t (g a)) -> Unit f -> t (Unit g) # | |
TraversableB (Const a :: (k -> Type) -> Type) | |
Defined in Data.Barbie.Internal.Traversable btraverse :: Applicative t => (forall (a0 :: k0). f a0 -> t (g a0)) -> Const a f -> t (Const a g) # | |
TraversableB b => TraversableB (Barbie b :: (k -> Type) -> Type) | |
Defined in Data.Barbie.Internal.Instances btraverse :: Applicative t => (forall (a :: k0). f a -> t (g a)) -> Barbie b f -> t (Barbie b g) # | |
TraversableB a => TraversableB (Tagged t a :: (Type -> Type) -> Type) Source # | |
Defined in Options.Harg.Het.Prod btraverse :: Applicative t0 => (forall (a0 :: k). f a0 -> t0 (g a0)) -> Tagged t a f -> t0 (Tagged t a g) # | |
(TraversableB a, TraversableB b) => TraversableB (Sum a b :: (k -> Type) -> Type) | |
Defined in Data.Barbie.Internal.Traversable btraverse :: Applicative t => (forall (a0 :: k0). f a0 -> t (g a0)) -> Sum a b f -> t (Sum a b g) # | |
(TraversableB a, TraversableB b) => TraversableB (Product a b :: (k -> Type) -> Type) | |
Defined in Data.Barbie.Internal.Traversable btraverse :: Applicative t => (forall (a0 :: k0). f a0 -> t (g a0)) -> Product a b f -> t (Product a b g) # | |
(Traversable f, TraversableB b) => TraversableB (Compose f b :: (k -> Type) -> Type) | |
Defined in Data.Barbie.Internal.Traversable btraverse :: Applicative t => (forall (a :: k0). f0 a -> t (g a)) -> Compose f b f0 -> t (Compose f b g) # | |
TraversableB EnvSource Source # | |
Defined in Options.Harg.Sources.Env btraverse :: Applicative t => (forall (a :: k). f a -> t (g a)) -> EnvSource f -> t (EnvSource g) # | |
TraversableB YAMLSource Source # | |
Defined in Options.Harg.Sources.YAML btraverse :: Applicative t => (forall (a :: k). f a -> t (g a)) -> YAMLSource f -> t (YAMLSource g) # | |
TraversableB JSONSource Source # | |
Defined in Options.Harg.Sources.JSON btraverse :: Applicative t => (forall (a :: k). f a -> t (g a)) -> JSONSource f -> t (JSONSource g) # | |
(TraversableB a, TraversableB b) => TraversableB (a :* b :: (Type -> Type) -> Type) Source # | |
Defined in Options.Harg.Het.Prod btraverse :: Applicative t => (forall (a0 :: k). f a0 -> t (g a0)) -> (a :* b) f -> t ((a :* b) g) # |
class FunctorB b => ProductB (b :: (k -> Type) -> Type) #
Barbie-types that can form products, subject to the laws:
bmap
(\(Pair
a _) -> a) .uncurry
bprod
=fst
bmap
(\(Pair
_ b) -> b) .uncurry
bprod
=snd
Notice that because of the laws, having an internal product structure is not enough to have a lawful instance. E.g.
data Ok f = Ok {o1 :: fString
, o2 :: fInt
} data Bad f = Bad{b1 :: fString
, hiddenFromArg:Int
} -- no lawful instance
Intuitively, the laws for this class require that b
hides no structure
from its argument f
. Because of this, if we are given any:
x :: forall a . f a
then this determines a unique value of type b f
, witnessed by the buniq
method.
For example:
buniq
x = Ok {o1 = x, o2 = x}
Formally, buniq
should satisfy:
const
(buniq
x) =bmap
(const
x)
There is a default implementation of bprod
and buniq
for Generic
types,
so instances can derived automatically.
Instances
(FunctorB (HKD structure), GProductB (Rep structure)) => ProductB (HKD structure :: (Type -> Type) -> Type) | |
ProductB (HKD b) => ProductB (Nested b :: (Type -> Type) -> Type) Source # | |
ProductB (Single a :: (Type -> Type) -> Type) Source # | |
ProductB (Proxy :: (k -> Type) -> Type) | |
ProductB (Unit :: (k -> Type) -> Type) | |
ProductB b => ProductB (Barbie b :: (k -> Type) -> Type) | |
ProductB a => ProductB (Tagged t a :: (Type -> Type) -> Type) Source # | |
(ProductB a, ProductB b) => ProductB (Product a b :: (k -> Type) -> Type) | |
ProductB EnvSource Source # | |
ProductB YAMLSource Source # | |
Defined in Options.Harg.Sources.YAML bprod :: YAMLSource f -> YAMLSource g -> YAMLSource (Product f g) # buniq :: (forall (a :: k). f a) -> YAMLSource f # | |
ProductB JSONSource Source # | |
Defined in Options.Harg.Sources.JSON bprod :: JSONSource f -> JSONSource g -> JSONSource (Product f g) # buniq :: (forall (a :: k). f a) -> JSONSource f # | |
(ProductB a, ProductB b) => ProductB (a :* b :: (Type -> Type) -> Type) Source # | |
data HKD structure (f :: Type -> Type) #
Higher-kinded data (HKD) is the design pattern in which every field in our
type is wrapped in some functor f
:
data User f = User { name :: f String , age :: f Int }
Depending on the functor, we can get different behaviours: with Maybe
, we
get a partial structure; with Validation
, we get a piecemeal validator;
and so on. The HKD
newtype allows us to lift any type into an HKD-style
API via its generic representation.
>>>
:set -XDeriveGeneric -XTypeApplications
>>>
:{
data User = User { name :: String, age :: Int } deriving Generic :}
The HKD
type is indexed by our choice of functor and the structure we're
lifting. In other words, we can define a synonym for our behaviour:
>>>
import Data.Monoid (Last (..))
>>>
type Partial a = HKD a Last
... and then we're ready to go!
>>>
mempty @(Partial User)
User {name = Last {getLast = Nothing}, age = Last {getLast = Nothing}}
>>>
mempty @(HKD (Int, Bool) [])
(,) [] []
Instances
GBuild f structure ([] :: [Type]) (HKD structure f) | |
Defined in Data.Generic.HKD.Build | |
(ProductB (HKD structure), ConstraintsB (HKD structure), GProductBC (Rep structure)) => ProductBC (HKD structure :: (Type -> Type) -> Type) | |
(FunctorB (HKD structure), GConstraintsB (Rep structure), GAllBC (Rep structure)) => ConstraintsB (HKD structure :: (Type -> Type) -> Type) | |
(FunctorB (HKD structure), GProductB (Rep structure)) => ProductB (HKD structure :: (Type -> Type) -> Type) | |
(FunctorB (HKD structure), GTraversableB (Rep structure)) => TraversableB (HKD structure :: (Type -> Type) -> Type) | |
Defined in Data.Generic.HKD.Types btraverse :: Applicative t => (forall (a :: k). f a -> t (g a)) -> HKD structure f -> t (HKD structure g) # | |
GFunctorB (Rep structure) => FunctorB (HKD structure :: (Type -> Type) -> Type) | |
Defined in Data.Generic.HKD.Types | |
(Eq tuple, Generic xs, Tuple f xs tuple) => Eq (HKD xs f) | |
(Ord tuple, Generic xs, Tuple f xs tuple) => Ord (HKD xs f) | |
Defined in Data.Generic.HKD.Types | |
(Generic structure, GShow True (HKD_ f structure)) => Show (HKD structure f) | |
(Semigroup tuple, Generic xs, Tuple f xs tuple) => Semigroup (HKD xs f) | |
(Monoid tuple, Generic xs, Tuple f xs tuple) => Monoid (HKD xs f) | |
(Generic structure, Function tuple, Tuple f structure tuple) => Function (HKD structure f) | |
(Arbitrary tuple, GToTuple (HKD_ f structure) tuple) => Arbitrary (HKD structure f) | |
(CoArbitrary tuple, GToTuple (HKD_ f structure) tuple) => CoArbitrary (HKD structure f) | |
Defined in Data.Generic.HKD.Types coarbitrary :: HKD structure f -> Gen b -> Gen b # | |
GFromJSON Zero (HKD_ f structure) => FromJSON (HKD structure f) Source # | |
type AllB (c :: Type -> Constraint) (HKD structure :: (Type -> Type) -> Type) | |
Defined in Data.Generic.HKD.Types |