| Safe Haskell | None |
|---|---|
| Language | Haskell2010 |
Data.Configifier
Contents
- data a :*> b = a :*> b
- data s :> t
- data a :>: s
- data ConfigCode k
- = Record (ConfigCode k) (ConfigCode k)
- | Label Symbol (ConfigCode k)
- | Descr (ConfigCode k) Symbol
- | List (ConfigCode k)
- | Option (ConfigCode k)
- | Type k
- type family ToConfigCode a :: ConfigCode *
- type family NoDesc a :: ConfigCode *
- type family ToConfig a f :: *
- data MaybeO a
- data Id a = Id a
- data Source
- = ConfigFileYaml SBS
- | ShellEnv [(String, String)]
- | CommandLine [String]
- data ConfigFile
- data ShellEnv
- data CommandLine
- data Tagged cfg = Tagged {
- fromTagged :: ToConfig cfg Id
- data TaggedM cfg = TaggedM {
- fromTaggedM :: ToConfig cfg Maybe
- type Result cfg = Either Error (Tagged cfg)
- data Error
- configify :: forall cfg tm. (tm ~ TaggedM cfg, Show tm, Monoid tm, Freeze cfg, FromJSON tm, HasParseShellEnv cfg, HasParseCommandLine cfg, CanonicalizePartial cfg) => [Source] -> Result cfg
- configify' :: forall cfg tm. (tm ~ TaggedM cfg, Show tm, Monoid tm, Freeze cfg, FromJSON tm, HasParseShellEnv cfg, HasParseCommandLine cfg, CanonicalizePartial cfg) => tm -> [Source] -> Result cfg
- parseConfigFile :: FromJSON (TaggedM cfg) => SBS -> Either Error (TaggedM cfg)
- renderConfigFile :: (Freeze cfg, t ~ Tagged cfg, ToJSON (TaggedM cfg)) => t -> SBS
- type Env = [(String, String)]
- class HasParseShellEnv cfg where
- parseShellEnv :: Env -> Either Error (TaggedM cfg)
- type Args = [String]
- class HasParseCommandLine cfg where
- parseCommandLine :: [String] -> Either Error (TaggedM cfg)
- primitiveParseCommandLine :: HasParseShellEnv cfg => [String] -> Either Error (TaggedM cfg)
- parseArgs :: Args -> Either String Env
- parseArgsWithEqSign :: String -> Either String Env
- parseArgsWithSpace :: String -> String -> Either String Env
- parseArgName :: String -> String
- (>>.) :: forall cfg ps r. (Sel cfg ps, ToValE cfg ps ~ Done r) => Tagged cfg -> Proxy ps -> r
- type family ToVal a p :: Maybe *
- type family OrElse x y :: Maybe k
- data CMaybe a where
- orElse :: CMaybe a -> CMaybe b -> CMaybe (OrElse a b)
- type family ToValueMaybe a :: Maybe *
- toValueMaybe :: CMaybe a -> CMaybe (ToValueMaybe a)
- class NothingValue a where
- nothingValue :: Proxy a -> CMaybe (ToValueMaybe a)
- class Sel cfg ps where
- class Sel' cfg ps where
- type ToValE a p = ToExc (LookupFailed a p) (ToVal a p)
- data Exc a b
- data LookupFailed a p
- type family ToExc a x :: Exc k l
- merge :: forall cfg tm ti. (tm ~ TaggedM cfg, ti ~ Tagged cfg, Freeze cfg, Monoid tm, CanonicalizePartial cfg) => [tm] -> Either Error ti
- freeze :: forall cfg tm ti. (tm ~ TaggedM cfg, ti ~ Tagged cfg, Freeze cfg) => tm -> Either Error ti
- thaw :: forall cfg tm ti. (tm ~ TaggedM cfg, ti ~ Tagged cfg, Freeze cfg) => ti -> tm
- class Freeze c where
- class CanonicalizePartial a where
- canonicalizePartial :: TaggedM a -> TaggedM a
- emptyPartial :: TaggedM a -> Bool
- docs :: (HasToDoc a, HasRenderDoc ConfigFile, HasRenderDoc ShellEnv, HasRenderDoc CommandLine) => Proxy a -> ST
- data Doc
- data DocOptional
- concatDoc :: Doc -> Doc -> Doc
- class HasToDoc a where
- class HasRenderDoc t where
config types
Construction of config records (cons for record fields).
Constructors
| a :*> b infixr 6 |
Construction of config record fields.
Add descriptive text to record field for documentation.
data ConfigCode k Source
Constructors
| Record (ConfigCode k) (ConfigCode k) infixr 6 | |
| Label Symbol (ConfigCode k) | |
| Descr (ConfigCode k) Symbol | |
| List (ConfigCode k) | |
| Option (ConfigCode k) | |
| Type k |
type family ToConfigCode a :: ConfigCode * Source
Map user-provided config type to ConfigCode types.
Equations
| ToConfigCode (a :*> b) = Record (ToConfigCode a) (ToConfigCode b) | |
| ToConfigCode (s :> a) = Label s (ToConfigCode a) | |
| ToConfigCode (a :>: s) = Descr (ToConfigCode a) s | |
| ToConfigCode [a] = List (ToConfigCode a) | |
| ToConfigCode (Maybe a) = Option (ToConfigCode a) | |
| ToConfigCode a = Type a |
type family NoDesc a :: ConfigCode * Source
Filter Descr constructors from ConfigCode.
Transformers' Identity is not in Typeable, so we roll our
own. It's also less work to write.
Constructors
| Id a |
sources
Constructors
| ConfigFileYaml SBS | |
| ShellEnv [(String, String)] | |
| CommandLine [String] |
data ConfigFile Source
Instances
Instances
data CommandLine Source
Instances
tagged values
Constructors
| Tagged | |
Fields
| |
Constructors
| TaggedM | |
Fields
| |
Instances
| Eq (ToConfig cfg Maybe) => Eq (TaggedM cfg) | |
| Show (ToConfig cfg Maybe) => Show (TaggedM cfg) | |
| ToJSON a => ToJSON (TaggedM (Type * a)) | instance ToJSON Type |
| ((~) * t (ToConfig cfg Maybe), (~) * (ToConfig (Option * cfg) Maybe) (MaybeO t''), ToJSON (TaggedM cfg)) => ToJSON (TaggedM (Option * cfg)) | instance ToJSON Option |
| ((~) * t (ToConfig cfg Maybe), ToJSON (TaggedM cfg)) => ToJSON (TaggedM (List * cfg)) | instance ToJSON List |
| (ToJSON (TaggedM cfg), KnownSymbol s) => ToJSON (TaggedM (Label * s cfg)) | instance ToJSON Label |
| ((~) * t1 (ToConfig cfg1 Maybe), ToJSON (TaggedM cfg1), (~) * t2 (ToConfig cfg2 Maybe), ToJSON (TaggedM cfg2)) => ToJSON (TaggedM (Record * cfg1 cfg2)) | instance ToJSON Record |
| FromJSON a => FromJSON (TaggedM (Type * a)) | instance FromJSON Type |
| FromJSON (TaggedM cfg) => FromJSON (TaggedM (Option * cfg)) | instance ParseJSON Option |
| FromJSON (TaggedM cfg) => FromJSON (TaggedM (List * cfg)) | instance ParseJSON List |
| (FromJSON (TaggedM cfg), KnownSymbol s) => FromJSON (TaggedM (Label * s cfg)) |
|
| (FromJSON (TaggedM cfg1), FromJSON (TaggedM cfg2)) => FromJSON (TaggedM (Record * cfg1 cfg2)) | instance FromJSON Record |
| Monoid (TaggedM a) => Monoid (TaggedM (Option * a)) | |
| Monoid (TaggedM (List * a)) | Lists are initialized empty by default. Append overwrites left values with right values. (If we tried to append list elements recursively, there would be awkward questions about matching list lengths.) |
| Monoid (TaggedM (Label * s (Type * a))) | There is no |
| Monoid (TaggedM a) => Monoid (TaggedM (Label * s a)) | If one of two configs is |
| (Monoid (TaggedM a), Monoid (TaggedM b)) => Monoid (TaggedM (Record * a b)) |
results and errors
Constructors
| InvalidYaml | |
Fields | |
| ShellEnvNil | |
| ShellEnvNoParse | |
Fields | |
| CommandLinePrimitiveParseError String | |
| CommandLinePrimitiveOtherError Error | |
| FreezeIncomplete | |
Fields | |
the main function
configify :: forall cfg tm. (tm ~ TaggedM cfg, Show tm, Monoid tm, Freeze cfg, FromJSON tm, HasParseShellEnv cfg, HasParseCommandLine cfg, CanonicalizePartial cfg) => [Source] -> Result cfg Source
configify' :: forall cfg tm. (tm ~ TaggedM cfg, Show tm, Monoid tm, Freeze cfg, FromJSON tm, HasParseShellEnv cfg, HasParseCommandLine cfg, CanonicalizePartial cfg) => tm -> [Source] -> Result cfg Source
yaml / json
shell env
class HasParseShellEnv cfg where Source
Instances
| (Typeable * a, FromJSON (TaggedM (Type * a))) => HasParseShellEnv (Type * a) | |
| HasParseShellEnv a => HasParseShellEnv (Option * a) | |
| HasParseShellEnv a => HasParseShellEnv (List * a) | You can provide a list value via the shell environment by providing a single element. This element will be put into a list implicitly. (A more general approach that allows for yaml-encoded list values in shell variables is more tricky to design, implement, and use: If you have a list of sub-configs and don't want the entire sub-config to be yaml-encoded, but use a longer shell variable name to go further down to deeper sub-configs, there is a lot of ambiguity. It may be possible to resolve that at run-time, but it's more tricky.) |
| (KnownSymbol path, HasParseShellEnv a) => HasParseShellEnv (Label * path a) | The paths into the recursive structure of the config file are concatenated to shell variable names with separating '_'. (It is still ok to have '_' in your config path names. This parser chops off complete matching names, whether they contain '_' or not, and only then worries about trailing '_'.) |
| (HasParseShellEnv a, HasParseShellEnv b) => HasParseShellEnv (Record * a b) |
cli
class HasParseCommandLine cfg where Source
Instances
| HasParseShellEnv cfg => HasParseCommandLine cfg |
primitiveParseCommandLine :: HasParseShellEnv cfg => [String] -> Either Error (TaggedM cfg) Source
Very basic fist approach: read --(key)(=|s+)(value);
construct shell env from keys and names, and use parseShellEnv on
the command line. If it doesn't like the syntax used in the
command line, it will crash. I hope for this to get much fancier
in the future.
parseArgName :: String -> String Source
accessing config values
(>>.) :: forall cfg ps r. (Sel cfg ps, ToValE cfg ps ~ Done r) => Tagged cfg -> Proxy ps -> r infix 7 Source
Map a Tagged config value and a type-level path to the part of
the config value the path points to. Trigger an informative type
error if path does not exist.
options
type family ToValueMaybe a :: Maybe * Source
Equations
| ToValueMaybe (Just x) = Just (Maybe x) | |
| ToValueMaybe Nothing = Nothing |
toValueMaybe :: CMaybe a -> CMaybe (ToValueMaybe a) Source
class NothingValue a where Source
Methods
nothingValue :: Proxy a -> CMaybe (ToValueMaybe a) Source
Instances
| NothingValue (Nothing *) | |
| NothingValue (Just * x) |
cfg traversal
Instances
| Sel' cfg ps => Sel cfg ps | |
| ((~) (ConfigCode *) cfg (Option * cfg'), NothingValue (ToVal cfg' ps), Sel cfg' ps) => Sel (Option * cfg') ps | |
| Sel (Record * cfg' cfg'') ([] Symbol) | |
| ((~) (ConfigCode *) cfg (Label * p cfg'), (~) * t (ToConfig cfg Id), Sel cfg' ps, KnownSymbol p) => Sel (Label * p cfg') ((:) Symbol p ps) | |
| ((~) (ConfigCode *) cfg (Record * cfg' cfg''), Sel cfg' ((:) Symbol p ps), Sel cfg'' ((:) Symbol p ps)) => Sel (Record * cfg' cfg'') ((:) Symbol p ps) |
static lookup error handling
type ToValE a p = ToExc (LookupFailed a p) (ToVal a p) Source
data LookupFailed a p Source
merge configs
merge :: forall cfg tm ti. (tm ~ TaggedM cfg, ti ~ Tagged cfg, Freeze cfg, Monoid tm, CanonicalizePartial cfg) => [tm] -> Either Error ti Source
freeze :: forall cfg tm ti. (tm ~ TaggedM cfg, ti ~ Tagged cfg, Freeze cfg) => tm -> Either Error ti Source
Instances
| Freeze (Type * c) | |
| ((~) * (ToConfig (Option * c) Maybe) (MaybeO tm), (~) * (ToConfig (Option * c) Id) (MaybeO ti), (~) * tm (ToConfig c Maybe), (~) * ti (ToConfig c Id), Freeze c) => Freeze (Option * c) | FIXME: if a non-optional part of an optional sub-config is
missing, the |
| Freeze c => Freeze (List * c) | |
| (KnownSymbol s, Freeze t) => Freeze (Label * s t) | |
| (Freeze a, Freeze b) => Freeze (Record * a b) |
class CanonicalizePartial a where Source
Instances
| CanonicalizePartial (Type * a) | |
| ((~) (ConfigCode *) cfg (Option * cfg'), CanonicalizePartial cfg') => CanonicalizePartial (Option * cfg') | |
| ((~) (ConfigCode *) cfg (List * cfg'), CanonicalizePartial cfg') => CanonicalizePartial (List * cfg') | |
| ((~) (ConfigCode *) cfg (Label * s cfg'), CanonicalizePartial cfg') => CanonicalizePartial (Label * s cfg') | |
| (CanonicalizePartial cfg, CanonicalizePartial cfg') => CanonicalizePartial (Record * cfg cfg') |
docs
docs :: (HasToDoc a, HasRenderDoc ConfigFile, HasRenderDoc ShellEnv, HasRenderDoc CommandLine) => Proxy a -> ST Source
Instances
| Typeable * a => HasToDoc (Type * a) | |
| HasToDoc a => HasToDoc (Option * a) | |
| HasToDoc a => HasToDoc (List * a) | |
| (HasToDoc a, KnownSymbol path, KnownSymbol descr) => HasToDoc (Descr * (Label * path a) descr) | |
| (KnownSymbol path, HasToDoc a) => HasToDoc (Label * path a) | |
| (HasToDoc a, HasToDoc b) => HasToDoc (Record * a b) |
class HasRenderDoc t where Source
Instances