    module System.Console.CmdArgs.Explicit.Type where

    import Control.Arrow
    import Control.Monad
    import Data.Char
    import Data.List
    import Data.Maybe
    import Data.Semigroup hiding (Arg)
    import Prelude

    -- | A name, either the name of a flag (@--/foo/@) or the name of a mode.
    type Name = String

    -- | A help message that goes with either a flag or a mode.
    type Help = String

    -- | The type of a flag, i.e. @--foo=/TYPE/@.
    type FlagHelp = String

    ---------------------------------------------------------------------
    -- UTILITY

    -- | Parse a boolean, accepts as True: true yes on enabled 1.
    parseBool :: String -> Maybe Bool
    parseBool :: [Char] -> Maybe Bool
    parseBool [Char]
    s | [Char]
    ls [Char] -> [[Char]] -> Bool
    forall a. Eq a => a -> [a] -> Bool
    forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
    `elem` [[Char]]
    true  = Bool -> Maybe Bool
    forall a. a -> Maybe a
    Just Bool
    True
                | [Char]
    ls [Char] -> [[Char]] -> Bool
    forall a. Eq a => a -> [a] -> Bool
    forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
    `elem` [[Char]]
    false = Bool -> Maybe Bool
    forall a. a -> Maybe a
    Just Bool
    False
                | Bool
    otherwise = Maybe Bool
    forall a. Maybe a
    Nothing
        where
            ls :: [Char]
    ls = (Char -> Char) -> [Char] -> [Char]
    forall a b. (a -> b) -> [a] -> [b]
    map Char -> Char
    toLower [Char]
    s
            true :: [[Char]]
    true = [[Char]
    "true",[Char]
    "yes",[Char]
    "on",[Char]
    "enabled",[Char]
    "1"]
            false :: [[Char]]
    false = [[Char]
    "false",[Char]
    "no",[Char]
    "off",[Char]
    "disabled",[Char]
    "0"]

    ---------------------------------------------------------------------
    -- GROUPS

    -- | A group of items (modes or flags). The items are treated as a list, but the
    --   group structure is used when displaying the help message.
    data Group a = Group
        {forall a. Group a -> [a]
    groupUnnamed :: [a] -- ^ Normal items.
        ,forall a. Group a -> [a]
    groupHidden :: [a] -- ^ Items that are hidden (not displayed in the help message).
        ,forall a. Group a -> [([Char], [a])]
    groupNamed :: [(Help, [a])] -- ^ Items that have been grouped, along with a description of each group.
        } deriving Int -> Group a -> [Char] -> [Char]
    [Group a] -> [Char] -> [Char]
    Group a -> [Char]
    (Int -> Group a -> [Char] -> [Char])
    -> (Group a -> [Char])
    -> ([Group a] -> [Char] -> [Char])
    -> Show (Group a)
    forall a. Show a => Int -> Group a -> [Char] -> [Char]
    forall a. Show a => [Group a] -> [Char] -> [Char]
    forall a. Show a => Group a -> [Char]
    forall a.
    (Int -> a -> [Char] -> [Char])
    -> (a -> [Char]) -> ([a] -> [Char] -> [Char]) -> Show a
    $cshowsPrec :: forall a. Show a => Int -> Group a -> [Char] -> [Char]
    showsPrec :: Int -> Group a -> [Char] -> [Char]
    $cshow :: forall a. Show a => Group a -> [Char]
    show :: Group a -> [Char]
    $cshowList :: forall a. Show a => [Group a] -> [Char] -> [Char]
    showList :: [Group a] -> [Char] -> [Char]
    Show

    instance Functor Group where
        fmap :: forall a b. (a -> b) -> Group a -> Group b
    fmap a -> b
    f (Group [a]
    a [a]
    b [([Char], [a])]
    c) = [b] -> [b] -> [([Char], [b])] -> Group b
    forall a. [a] -> [a] -> [([Char], [a])] -> Group a
    Group ((a -> b) -> [a] -> [b]
    forall a b. (a -> b) -> [a] -> [b]
    map a -> b
    f [a]
    a) ((a -> b) -> [a] -> [b]
    forall a b. (a -> b) -> [a] -> [b]
    map a -> b
    f [a]
    b) ((([Char], [a]) -> ([Char], [b]))
    -> [([Char], [a])] -> [([Char], [b])]
    forall a b. (a -> b) -> [a] -> [b]
    map (([a] -> [b]) -> ([Char], [a]) -> ([Char], [b])
    forall b c d. (b -> c) -> (d, b) -> (d, c)
    forall (a :: * -> * -> *) b c d.
    Arrow a =>
    a b c -> a (d, b) (d, c)
    second (([a] -> [b]) -> ([Char], [a]) -> ([Char], [b]))
    -> ([a] -> [b]) -> ([Char], [a]) -> ([Char], [b])
    forall a b. (a -> b) -> a -> b
    $ (a -> b) -> [a] -> [b]
    forall a b. (a -> b) -> [a] -> [b]
    map a -> b
    f) [([Char], [a])]
    c)

    instance Semigroup (Group a) where
        Group [a]
    x1 [a]
    x2 [([Char], [a])]
    x3 <> :: Group a -> Group a -> Group a
    <> Group [a]
    y1 [a]
    y2 [([Char], [a])]
    y3 = [a] -> [a] -> [([Char], [a])] -> Group a
    forall a. [a] -> [a] -> [([Char], [a])] -> Group a
    Group ([a]
    x1[a] -> [a] -> [a]
    forall a. [a] -> [a] -> [a]
    ++[a]
    y1) ([a]
    x2[a] -> [a] -> [a]
    forall a. [a] -> [a] -> [a]
    ++[a]
    y2) ([([Char], [a])]
    x3[([Char], [a])] -> [([Char], [a])] -> [([Char], [a])]
    forall a. [a] -> [a] -> [a]
    ++[([Char], [a])]
    y3)

    instance Monoid (Group a) where
        mempty :: Group a
    mempty = [a] -> [a] -> [([Char], [a])] -> Group a
    forall a. [a] -> [a] -> [([Char], [a])] -> Group a
    Group [] [] []
        mappend :: Group a -> Group a -> Group a
    mappend = Group a -> Group a -> Group a
    forall a. Semigroup a => a -> a -> a
    (<>)

    -- | Convert a group into a list.
    fromGroup :: Group a -> [a]
    fromGroup :: forall a. Group a -> [a]
    fromGroup (Group [a]
    x [a]
    y [([Char], [a])]
    z) = [a]
    x [a] -> [a] -> [a]
    forall a. [a] -> [a] -> [a]
    ++ [a]
    y [a] -> [a] -> [a]
    forall a. [a] -> [a] -> [a]
    ++ (([Char], [a]) -> [a]) -> [([Char], [a])] -> [a]
    forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
    concatMap ([Char], [a]) -> [a]
    forall a b. (a, b) -> b
    snd [([Char], [a])]
    z

    -- | Convert a list into a group, placing all fields in 'groupUnnamed'.
    toGroup :: [a] -> Group a
    toGroup :: forall a. [a] -> Group a
    toGroup [a]
    x = [a] -> [a] -> [([Char], [a])] -> Group a
    forall a. [a] -> [a] -> [([Char], [a])] -> Group a
    Group [a]
    x [] []

    ---------------------------------------------------------------------
    -- TYPES

    -- | A mode. Do not use the 'Mode' constructor directly, instead
    --   use 'mode' to construct the 'Mode' and then record updates.
    --   Each mode has three main features:
    --
    --   * A list of submodes ('modeGroupModes')
    --
    --   * A list of flags ('modeGroupFlags')
    --
    --   * Optionally an unnamed argument ('modeArgs')
    --
    --  To produce the help information for a mode, either use 'helpText' or 'show'.
    data Mode a = Mode
        {forall a. Mode a -> Group (Mode a)
    modeGroupModes :: Group (Mode a) -- ^ The available sub-modes
        ,forall a. Mode a -> [[Char]]
    modeNames :: [Name] -- ^ The names assigned to this mode (for the root mode, this name is used as the program name)
        ,forall a. Mode a -> a
    modeValue :: a -- ^ Value to start with
        ,forall a. Mode a -> a -> Either [Char] a
    modeCheck :: a -> Either String a -- ^ Check the value reprsented by a mode is correct, after applying all flags
        ,forall a. Mode a -> a -> Maybe [[Char]]
    modeReform :: a -> Maybe [String] -- ^ Given a value, try to generate the input arguments.
        ,forall a. Mode a -> Bool
    modeExpandAt :: Bool -- ^ Expand @\@@ arguments with 'expandArgsAt', defaults to 'True', only applied if using an 'IO' processing function.
                              --   Only the root 'Mode's value will be used.
        ,forall a. Mode a -> [Char]
    modeHelp :: Help -- ^ Help text
        ,forall a. Mode a -> [[Char]]
    modeHelpSuffix :: [String] -- ^ A longer help suffix displayed after a mode
        ,forall a. Mode a -> ([Arg a], Maybe (Arg a))
    modeArgs :: ([Arg a], Maybe (Arg a)) -- ^ The unnamed arguments, a series of arguments, followed optionally by one for all remaining slots
        ,forall a. Mode a -> Group (Flag a)
    modeGroupFlags :: Group (Flag a) -- ^ Groups of flags
        }

    -- | Extract the modes from a 'Mode'
    modeModes :: Mode a -> [Mode a]
    modeModes :: forall a. Mode a -> [Mode a]
    modeModes = Group (Mode a) -> [Mode a]
    forall a. Group a -> [a]
    fromGroup (Group (Mode a) -> [Mode a])
    -> (Mode a -> Group (Mode a)) -> Mode a -> [Mode a]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Mode a -> Group (Mode a)
    forall a. Mode a -> Group (Mode a)
    modeGroupModes

    -- | Extract the flags from a 'Mode'
    modeFlags :: Mode a -> [Flag a]
    modeFlags :: forall a. Mode a -> [Flag a]
    modeFlags = Group (Flag a) -> [Flag a]
    forall a. Group a -> [a]
    fromGroup (Group (Flag a) -> [Flag a])
    -> (Mode a -> Group (Flag a)) -> Mode a -> [Flag a]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Mode a -> Group (Flag a)
    forall a. Mode a -> Group (Flag a)
    modeGroupFlags

    -- | The 'FlagInfo' type has the following meaning:
    --
    --
    -- >              FlagReq     FlagOpt      FlagOptRare/FlagNone
    -- > -xfoo        -x=foo      -x=foo       -x -foo
    -- > -x foo       -x=foo      -x foo       -x foo
    -- > -x=foo       -x=foo      -x=foo       -x=foo
    -- > --xx foo     --xx=foo    --xx foo     --xx foo
    -- > --xx=foo     --xx=foo    --xx=foo     --xx=foo
    data FlagInfo
        = FlagReq             -- ^ Required argument
        | FlagOpt String      -- ^ Optional argument
        | FlagOptRare String  -- ^ Optional argument that requires an = before the value
        | FlagNone            -- ^ No argument
          deriving (FlagInfo -> FlagInfo -> Bool
    (FlagInfo -> FlagInfo -> Bool)
    -> (FlagInfo -> FlagInfo -> Bool) -> Eq FlagInfo
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: FlagInfo -> FlagInfo -> Bool
    == :: FlagInfo -> FlagInfo -> Bool
    $c/= :: FlagInfo -> FlagInfo -> Bool
    /= :: FlagInfo -> FlagInfo -> Bool
    Eq,Eq FlagInfo
    Eq FlagInfo
    -> (FlagInfo -> FlagInfo -> Ordering)
    -> (FlagInfo -> FlagInfo -> Bool)
    -> (FlagInfo -> FlagInfo -> Bool)
    -> (FlagInfo -> FlagInfo -> Bool)
    -> (FlagInfo -> FlagInfo -> Bool)
    -> (FlagInfo -> FlagInfo -> FlagInfo)
    -> (FlagInfo -> FlagInfo -> FlagInfo)
    -> Ord FlagInfo
    FlagInfo -> FlagInfo -> Bool
    FlagInfo -> FlagInfo -> Ordering
    FlagInfo -> FlagInfo -> FlagInfo
    forall a.
    Eq a
    -> (a -> a -> Ordering)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> a)
    -> (a -> a -> a)
    -> Ord a
    $ccompare :: FlagInfo -> FlagInfo -> Ordering
    compare :: FlagInfo -> FlagInfo -> Ordering
    $c< :: FlagInfo -> FlagInfo -> Bool
    < :: FlagInfo -> FlagInfo -> Bool
    $c<= :: FlagInfo -> FlagInfo -> Bool
    <= :: FlagInfo -> FlagInfo -> Bool
    $c> :: FlagInfo -> FlagInfo -> Bool
    > :: FlagInfo -> FlagInfo -> Bool
    $c>= :: FlagInfo -> FlagInfo -> Bool
    >= :: FlagInfo -> FlagInfo -> Bool
    $cmax :: FlagInfo -> FlagInfo -> FlagInfo
    max :: FlagInfo -> FlagInfo -> FlagInfo
    $cmin :: FlagInfo -> FlagInfo -> FlagInfo
    min :: FlagInfo -> FlagInfo -> FlagInfo
    Ord,Int -> FlagInfo -> [Char] -> [Char]
    [FlagInfo] -> [Char] -> [Char]
    FlagInfo -> [Char]
    (Int -> FlagInfo -> [Char] -> [Char])
    -> (FlagInfo -> [Char])
    -> ([FlagInfo] -> [Char] -> [Char])
    -> Show FlagInfo
    forall a.
    (Int -> a -> [Char] -> [Char])
    -> (a -> [Char]) -> ([a] -> [Char] -> [Char]) -> Show a
    $cshowsPrec :: Int -> FlagInfo -> [Char] -> [Char]
    showsPrec :: Int -> FlagInfo -> [Char] -> [Char]
    $cshow :: FlagInfo -> [Char]
    show :: FlagInfo -> [Char]
    $cshowList :: [FlagInfo] -> [Char] -> [Char]
    showList :: [FlagInfo] -> [Char] -> [Char]
    Show)

    -- | Extract the value from inside a 'FlagOpt' or 'FlagOptRare', or raises an error.
    fromFlagOpt :: FlagInfo -> String
    fromFlagOpt :: FlagInfo -> [Char]
    fromFlagOpt (FlagOpt [Char]
    x) = [Char]
    x
    fromFlagOpt (FlagOptRare [Char]
    x) = [Char]
    x

    -- | A function to take a string, and a value, and either produce an error message
    --   (@Left@), or a modified value (@Right@).
    type Update a = String -> a -> Either String a

    -- | A flag, consisting of a list of flag names and other information.
    data Flag a = Flag
        {forall a. Flag a -> [[Char]]
    flagNames :: [Name] -- ^ The names for the flag.
        ,forall a. Flag a -> FlagInfo
    flagInfo :: FlagInfo -- ^ Information about a flag's arguments.
        ,forall a. Flag a -> Update a
    flagValue :: Update a -- ^ The way of processing a flag.
        ,forall a. Flag a -> [Char]
    flagType :: FlagHelp -- ^ The type of data for the flag argument, i.e. FILE\/DIR\/EXT
        ,forall a. Flag a -> [Char]
    flagHelp :: Help -- ^ The help message associated with this flag.
        }

    -- | An unnamed argument. Anything not starting with @-@ is considered an argument,
    --   apart from @\"-\"@ which is considered to be the argument @\"-\"@, and any arguments
    --   following @\"--\"@. For example:
    --
    -- > programname arg1 -j - --foo arg3 -- -arg4 --arg5=1 arg6
    --
    --   Would have the arguments:
    --
    -- > ["arg1","-","arg3","-arg4","--arg5=1","arg6"]
    data Arg a = Arg
        {forall a. Arg a -> Update a
    argValue :: Update a -- ^ A way of processing the argument.
        ,forall a. Arg a -> [Char]
    argType :: FlagHelp -- ^ The type of data for the argument, i.e. FILE\/DIR\/EXT
        ,forall a. Arg a -> Bool
    argRequire :: Bool -- ^ Is at least one of these arguments required, the command line will fail if none are set
        }

    ---------------------------------------------------------------------
    -- CHECK FLAGS

    -- | Check that a mode is well formed.
    checkMode :: Mode a -> Maybe String
    checkMode :: forall a. Mode a -> Maybe [Char]
    checkMode Mode a
    x = [Maybe [Char]] -> Maybe [Char]
    forall (t :: * -> *) (m :: * -> *) a.
    (Foldable t, MonadPlus m) =>
    t (m a) -> m a
    msum
        [[Char] -> [[Char]] -> Maybe [Char]
    checkNames [Char]
    "modes" ([[Char]] -> Maybe [Char]) -> [[Char]] -> Maybe [Char]
    forall a b. (a -> b) -> a -> b
    $ (Mode a -> [[Char]]) -> [Mode a] -> [[Char]]
    forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
    concatMap Mode a -> [[Char]]
    forall a. Mode a -> [[Char]]
    modeNames ([Mode a] -> [[Char]]) -> [Mode a] -> [[Char]]
    forall a b. (a -> b) -> a -> b
    $ Mode a -> [Mode a]
    forall a. Mode a -> [Mode a]
    modeModes Mode a
    x
        ,[Maybe [Char]] -> Maybe [Char]
    forall (t :: * -> *) (m :: * -> *) a.
    (Foldable t, MonadPlus m) =>
    t (m a) -> m a
    msum ([Maybe [Char]] -> Maybe [Char]) -> [Maybe [Char]] -> Maybe [Char]
    forall a b. (a -> b) -> a -> b
    $ (Mode a -> Maybe [Char]) -> [Mode a] -> [Maybe [Char]]
    forall a b. (a -> b) -> [a] -> [b]
    map Mode a -> Maybe [Char]
    forall a. Mode a -> Maybe [Char]
    checkMode ([Mode a] -> [Maybe [Char]]) -> [Mode a] -> [Maybe [Char]]
    forall a b. (a -> b) -> a -> b
    $ Mode a -> [Mode a]
    forall a. Mode a -> [Mode a]
    modeModes Mode a
    x
        ,Group (Mode a) -> Maybe [Char]
    forall a. Group a -> Maybe [Char]
    checkGroup (Group (Mode a) -> Maybe [Char]) -> Group (Mode a) -> Maybe [Char]
    forall a b. (a -> b) -> a -> b
    $ Mode a -> Group (Mode a)
    forall a. Mode a -> Group (Mode a)
    modeGroupModes Mode a
    x
        ,Group (Flag a) -> Maybe [Char]
    forall a. Group a -> Maybe [Char]
    checkGroup (Group (Flag a) -> Maybe [Char]) -> Group (Flag a) -> Maybe [Char]
    forall a b. (a -> b) -> a -> b
    $ Mode a -> Group (Flag a)
    forall a. Mode a -> Group (Flag a)
    modeGroupFlags Mode a
    x
        ,[Char] -> [[Char]] -> Maybe [Char]
    checkNames [Char]
    "flag names" ([[Char]] -> Maybe [Char]) -> [[Char]] -> Maybe [Char]
    forall a b. (a -> b) -> a -> b
    $ (Flag a -> [[Char]]) -> [Flag a] -> [[Char]]
    forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
    concatMap Flag a -> [[Char]]
    forall a. Flag a -> [[Char]]
    flagNames ([Flag a] -> [[Char]]) -> [Flag a] -> [[Char]]
    forall a b. (a -> b) -> a -> b
    $ Mode a -> [Flag a]
    forall a. Mode a -> [Flag a]
    modeFlags Mode a
    x]
        where
            checkGroup :: Group a -> Maybe String
            checkGroup :: forall a. Group a -> Maybe [Char]
    checkGroup Group a
    x = [Maybe [Char]] -> Maybe [Char]
    forall (t :: * -> *) (m :: * -> *) a.
    (Foldable t, MonadPlus m) =>
    t (m a) -> m a
    msum
                [[Char] -> Bool -> Maybe [Char]
    check [Char]
    "Empty group name" (Bool -> Maybe [Char]) -> Bool -> Maybe [Char]
    forall a b. (a -> b) -> a -> b
    $ Bool -> Bool
    not (Bool -> Bool) -> Bool -> Bool
    forall a b. (a -> b) -> a -> b
    $ (([Char], [a]) -> Bool) -> [([Char], [a])] -> Bool
    forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
    any ([Char] -> Bool
    forall a. [a] -> Bool
    forall (t :: * -> *) a. Foldable t => t a -> Bool
    null ([Char] -> Bool)
    -> (([Char], [a]) -> [Char]) -> ([Char], [a]) -> Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ([Char], [a]) -> [Char]
    forall a b. (a, b) -> a
    fst) ([([Char], [a])] -> Bool) -> [([Char], [a])] -> Bool
    forall a b. (a -> b) -> a -> b
    $ Group a -> [([Char], [a])]
    forall a. Group a -> [([Char], [a])]
    groupNamed Group a
    x
                ,[Char] -> Bool -> Maybe [Char]
    check [Char]
    "Empty group contents" (Bool -> Maybe [Char]) -> Bool -> Maybe [Char]
    forall a b. (a -> b) -> a -> b
    $ Bool -> Bool
    not (Bool -> Bool) -> Bool -> Bool
    forall a b. (a -> b) -> a -> b
    $ (([Char], [a]) -> Bool) -> [([Char], [a])] -> Bool
    forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
    any ([a] -> Bool
    forall a. [a] -> Bool
    forall (t :: * -> *) a. Foldable t => t a -> Bool
    null ([a] -> Bool) -> (([Char], [a]) -> [a]) -> ([Char], [a]) -> Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ([Char], [a]) -> [a]
    forall a b. (a, b) -> b
    snd) ([([Char], [a])] -> Bool) -> [([Char], [a])] -> Bool
    forall a b. (a -> b) -> a -> b
    $ Group a -> [([Char], [a])]
    forall a. Group a -> [([Char], [a])]
    groupNamed Group a
    x]

            checkNames :: String -> [Name] -> Maybe String
            checkNames :: [Char] -> [[Char]] -> Maybe [Char]
    checkNames [Char]
    msg [[Char]]
    xs = [Char] -> Bool -> Maybe [Char]
    check [Char]
    "Empty names" (Bool -> Bool
    not (([Char] -> Bool) -> [[Char]] -> Bool
    forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
    any [Char] -> Bool
    forall a. [a] -> Bool
    forall (t :: * -> *) a. Foldable t => t a -> Bool
    null [[Char]]
    xs)) Maybe [Char] -> Maybe [Char] -> Maybe [Char]
    forall a. Maybe a -> Maybe a -> Maybe a
    forall (m :: * -> *) a. MonadPlus m => m a -> m a -> m a
    `mplus` do
                [Char]
    bad <- [[Char]] -> Maybe [Char]
    forall a. [a] -> Maybe a
    listToMaybe ([[Char]] -> Maybe [Char]) -> [[Char]] -> Maybe [Char]
    forall a b. (a -> b) -> a -> b
    $ [[Char]]
    xs [[Char]] -> [[Char]] -> [[Char]]
    forall a. Eq a => [a] -> [a] -> [a]
    \\ [[Char]] -> [[Char]]
    forall a. Eq a => [a] -> [a]
    nub [[Char]]
    xs
                let dupe :: [[Char]]
    dupe = ([Char] -> Bool) -> [[Char]] -> [[Char]]
    forall a. (a -> Bool) -> [a] -> [a]
    filter ([Char] -> [Char] -> Bool
    forall a. Eq a => a -> a -> Bool
    == [Char]
    bad) [[Char]]
    xs
                [Char] -> Maybe [Char]
    forall a. a -> Maybe a
    forall (m :: * -> *) a. Monad m => a -> m a
    return ([Char] -> Maybe [Char]) -> [Char] -> Maybe [Char]
    forall a b. (a -> b) -> a -> b
    $ [Char]
    "Sanity check failed, multiple " [Char] -> [Char] -> [Char]
    forall a. [a] -> [a] -> [a]
    ++ [Char]
    msg [Char] -> [Char] -> [Char]
    forall a. [a] -> [a] -> [a]
    ++ [Char]
    ": " [Char] -> [Char] -> [Char]
    forall a. [a] -> [a] -> [a]
    ++ [[Char]] -> [Char]
    unwords (([Char] -> [Char]) -> [[Char]] -> [[Char]]
    forall a b. (a -> b) -> [a] -> [b]
    map [Char] -> [Char]
    forall a. Show a => a -> [Char]
    show [[Char]]
    dupe)

            check :: String -> Bool -> Maybe String
            check :: [Char] -> Bool -> Maybe [Char]
    check [Char]
    msg Bool
    True = Maybe [Char]
    forall a. Maybe a
    Nothing
            check [Char]
    msg Bool
    False = [Char] -> Maybe [Char]
    forall a. a -> Maybe a
    Just [Char]
    msg

    ---------------------------------------------------------------------
    -- REMAP

    -- | Like functor, but where the the argument isn't just covariant.
    class Remap m where
        -- | Convert between two values.
        remap :: (a -> b) -- ^ Embed a value
              -> (b -> (a, a -> b)) -- ^ Extract the mode and give a way of re-embedding
              -> m a -> m b

    -- | Restricted version of 'remap' where the values are isomorphic.
    remap2 :: Remap m => (a -> b) -> (b -> a) -> m a -> m b
    remap2 :: forall (m :: * -> *) a b.
    Remap m =>
    (a -> b) -> (b -> a) -> m a -> m b
    remap2 a -> b
    f b -> a
    g = (a -> b) -> (b -> (a, a -> b)) -> m a -> m b
    forall a b. (a -> b) -> (b -> (a, a -> b)) -> m a -> m b
    forall (m :: * -> *) a b.
    Remap m =>
    (a -> b) -> (b -> (a, a -> b)) -> m a -> m b
    remap a -> b
    f (\b
    x -> (b -> a
    g b
    x, a -> b
    f))

    instance Remap Mode where
        remap :: forall a b. (a -> b) -> (b -> (a, a -> b)) -> Mode a -> Mode b
    remap a -> b
    f b -> (a, a -> b)
    g Mode a
    x = Mode a
    x
            {modeGroupModes :: Group (Mode b)
    modeGroupModes = (Mode a -> Mode b) -> Group (Mode a) -> Group (Mode b)
    forall a b. (a -> b) -> Group a -> Group b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap ((a -> b) -> (b -> (a, a -> b)) -> Mode a -> Mode b
    forall a b. (a -> b) -> (b -> (a, a -> b)) -> Mode a -> Mode b
    forall (m :: * -> *) a b.
    Remap m =>
    (a -> b) -> (b -> (a, a -> b)) -> m a -> m b
    remap a -> b
    f b -> (a, a -> b)
    g) (Group (Mode a) -> Group (Mode b))
    -> Group (Mode a) -> Group (Mode b)
    forall a b. (a -> b) -> a -> b
    $ Mode a -> Group (Mode a)
    forall a. Mode a -> Group (Mode a)
    modeGroupModes Mode a
    x
            ,modeValue :: b
    modeValue = a -> b
    f (a -> b) -> a -> b
    forall a b. (a -> b) -> a -> b
    $ Mode a -> a
    forall a. Mode a -> a
    modeValue Mode a
    x
            ,modeCheck :: b -> Either [Char] b
    modeCheck = \b
    v -> let (a
    a,a -> b
    b) = b -> (a, a -> b)
    g b
    v in (a -> b) -> Either [Char] a -> Either [Char] b
    forall a b. (a -> b) -> Either [Char] a -> Either [Char] b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap a -> b
    b (Either [Char] a -> Either [Char] b)
    -> Either [Char] a -> Either [Char] b
    forall a b. (a -> b) -> a -> b
    $ Mode a -> a -> Either [Char] a
    forall a. Mode a -> a -> Either [Char] a
    modeCheck Mode a
    x a
    a
            ,modeReform :: b -> Maybe [[Char]]
    modeReform = Mode a -> a -> Maybe [[Char]]
    forall a. Mode a -> a -> Maybe [[Char]]
    modeReform Mode a
    x (a -> Maybe [[Char]]) -> (b -> a) -> b -> Maybe [[Char]]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (a, a -> b) -> a
    forall a b. (a, b) -> a
    fst ((a, a -> b) -> a) -> (b -> (a, a -> b)) -> b -> a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . b -> (a, a -> b)
    g
            ,modeArgs :: ([Arg b], Maybe (Arg b))
    modeArgs = ((Arg a -> Arg b) -> [Arg a] -> [Arg b]
    forall a b. (a -> b) -> [a] -> [b]
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap ((a -> b) -> (b -> (a, a -> b)) -> Arg a -> Arg b
    forall a b. (a -> b) -> (b -> (a, a -> b)) -> Arg a -> Arg b
    forall (m :: * -> *) a b.
    Remap m =>
    (a -> b) -> (b -> (a, a -> b)) -> m a -> m b
    remap a -> b
    f b -> (a, a -> b)
    g) ([Arg a] -> [Arg b])
    -> (Maybe (Arg a) -> Maybe (Arg b))
    -> ([Arg a], Maybe (Arg a))
    -> ([Arg b], Maybe (Arg b))
    forall b c b' c'. (b -> c) -> (b' -> c') -> (b, b') -> (c, c')
    forall (a :: * -> * -> *) b c b' c'.
    Arrow a =>
    a b c -> a b' c' -> a (b, b') (c, c')
    *** (Arg a -> Arg b) -> Maybe (Arg a) -> Maybe (Arg b)
    forall a b. (a -> b) -> Maybe a -> Maybe b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap ((a -> b) -> (b -> (a, a -> b)) -> Arg a -> Arg b
    forall a b. (a -> b) -> (b -> (a, a -> b)) -> Arg a -> Arg b
    forall (m :: * -> *) a b.
    Remap m =>
    (a -> b) -> (b -> (a, a -> b)) -> m a -> m b
    remap a -> b
    f b -> (a, a -> b)
    g)) (([Arg a], Maybe (Arg a)) -> ([Arg b], Maybe (Arg b)))
    -> ([Arg a], Maybe (Arg a)) -> ([Arg b], Maybe (Arg b))
    forall a b. (a -> b) -> a -> b
    $ Mode a -> ([Arg a], Maybe (Arg a))
    forall a. Mode a -> ([Arg a], Maybe (Arg a))
    modeArgs Mode a
    x
            ,modeGroupFlags :: Group (Flag b)
    modeGroupFlags = (Flag a -> Flag b) -> Group (Flag a) -> Group (Flag b)
    forall a b. (a -> b) -> Group a -> Group b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap ((a -> b) -> (b -> (a, a -> b)) -> Flag a -> Flag b
    forall a b. (a -> b) -> (b -> (a, a -> b)) -> Flag a -> Flag b
    forall (m :: * -> *) a b.
    Remap m =>
    (a -> b) -> (b -> (a, a -> b)) -> m a -> m b
    remap a -> b
    f b -> (a, a -> b)
    g) (Group (Flag a) -> Group (Flag b))
    -> Group (Flag a) -> Group (Flag b)
    forall a b. (a -> b) -> a -> b
    $ Mode a -> Group (Flag a)
    forall a. Mode a -> Group (Flag a)
    modeGroupFlags Mode a
    x}

    instance Remap Flag where
        remap :: forall a b. (a -> b) -> (b -> (a, a -> b)) -> Flag a -> Flag b
    remap a -> b
    f b -> (a, a -> b)
    g Flag a
    x = Flag a
    x{flagValue :: Update b
    flagValue = (a -> b) -> (b -> (a, a -> b)) -> Update a -> Update b
    forall a b. (a -> b) -> (b -> (a, a -> b)) -> Update a -> Update b
    remapUpdate a -> b
    f b -> (a, a -> b)
    g (Update a -> Update b) -> Update a -> Update b
    forall a b. (a -> b) -> a -> b
    $ Flag a -> Update a
    forall a. Flag a -> Update a
    flagValue Flag a
    x}

    instance Remap Arg where
        remap :: forall a b. (a -> b) -> (b -> (a, a -> b)) -> Arg a -> Arg b
    remap a -> b
    f b -> (a, a -> b)
    g Arg a
    x = Arg a
    x{argValue :: Update b
    argValue = (a -> b) -> (b -> (a, a -> b)) -> Update a -> Update b
    forall a b. (a -> b) -> (b -> (a, a -> b)) -> Update a -> Update b
    remapUpdate a -> b
    f b -> (a, a -> b)
    g (Update a -> Update b) -> Update a -> Update b
    forall a b. (a -> b) -> a -> b
    $ Arg a -> Update a
    forall a. Arg a -> Update a
    argValue Arg a
    x}

    -- | Version of 'remap' for the 'Update' type alias.
    remapUpdate :: (a -> b) -> (b -> (a, a -> b)) -> Update a -> Update b
    remapUpdate :: forall a b. (a -> b) -> (b -> (a, a -> b)) -> Update a -> Update b
    remapUpdate a -> b
    f b -> (a, a -> b)
    g Update a
    upd = \[Char]
    s b
    v -> let (a
    a,a -> b
    b) = b -> (a, a -> b)
    g b
    v in (a -> b) -> Either [Char] a -> Either [Char] b
    forall a b. (a -> b) -> Either [Char] a -> Either [Char] b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap a -> b
    b (Either [Char] a -> Either [Char] b)
    -> Either [Char] a -> Either [Char] b
    forall a b. (a -> b) -> a -> b
    $ Update a
    upd [Char]
    s a
    a

    ---------------------------------------------------------------------
    -- MODE/MODES CREATORS

    -- | Create an empty mode specifying only 'modeValue'. All other fields will usually be populated
    --   using record updates.
    modeEmpty :: a -> Mode a
    modeEmpty :: forall a. a -> Mode a
    modeEmpty a
    x = Group (Mode a)
    -> [[Char]]
    -> a
    -> (a -> Either [Char] a)
    -> (a -> Maybe [[Char]])
    -> Bool
    -> [Char]
    -> [[Char]]
    -> ([Arg a], Maybe (Arg a))
    -> Group (Flag a)
    -> Mode a
    forall a.
    Group (Mode a)
    -> [[Char]]
    -> a
    -> (a -> Either [Char] a)
    -> (a -> Maybe [[Char]])
    -> Bool
    -> [Char]
    -> [[Char]]
    -> ([Arg a], Maybe (Arg a))
    -> Group (Flag a)
    -> Mode a
    Mode Group (Mode a)
    forall a. Monoid a => a
    mempty [] a
    x a -> Either [Char] a
    forall a b. b -> Either a b
    Right (Maybe [[Char]] -> a -> Maybe [[Char]]
    forall a b. a -> b -> a
    const Maybe [[Char]]
    forall a. Maybe a
    Nothing) Bool
    True [Char]
    "" [] ([],Maybe (Arg a)
    forall a. Maybe a
    Nothing) Group (Flag a)
    forall a. Monoid a => a
    mempty

    -- | Create a mode with a name, an initial value, some help text, a way of processing arguments
    --   and a list of flags.
    mode :: Name -> a -> Help -> Arg a -> [Flag a] -> Mode a
    mode :: forall a. [Char] -> a -> [Char] -> Arg a -> [Flag a] -> Mode a
    mode [Char]
    name a
    value [Char]
    help Arg a
    arg [Flag a]
    flags = (a -> Mode a
    forall a. a -> Mode a
    modeEmpty a
    value){modeNames :: [[Char]]
    modeNames=[[Char]
    name], modeHelp :: [Char]
    modeHelp=[Char]
    help, modeArgs :: ([Arg a], Maybe (Arg a))
    modeArgs=([],Arg a -> Maybe (Arg a)
    forall a. a -> Maybe a
    Just Arg a
    arg), modeGroupFlags :: Group (Flag a)
    modeGroupFlags=[Flag a] -> Group (Flag a)
    forall a. [a] -> Group a
    toGroup [Flag a]
    flags}

    -- | Create a list of modes, with a program name, an initial value, some help text and the child modes.
    modes :: String -> a -> Help -> [Mode a] -> Mode a
    modes :: forall a. [Char] -> a -> [Char] -> [Mode a] -> Mode a
    modes [Char]
    name a
    value [Char]
    help [Mode a]
    xs = (a -> Mode a
    forall a. a -> Mode a
    modeEmpty a
    value){modeNames :: [[Char]]
    modeNames=[[Char]
    name], modeHelp :: [Char]
    modeHelp=[Char]
    help, modeGroupModes :: Group (Mode a)
    modeGroupModes=[Mode a] -> Group (Mode a)
    forall a. [a] -> Group a
    toGroup [Mode a]
    xs}

    ---------------------------------------------------------------------
    -- FLAG CREATORS

    -- | Create a flag taking no argument value, with a list of flag names, an update function
    --   and some help text.
    flagNone :: [Name] -> (a -> a) -> Help -> Flag a
    flagNone :: forall a. [[Char]] -> (a -> a) -> [Char] -> Flag a
    flagNone [[Char]]
    names a -> a
    f [Char]
    help = [[Char]] -> FlagInfo -> Update a -> [Char] -> [Char] -> Flag a
    forall a.
    [[Char]] -> FlagInfo -> Update a -> [Char] -> [Char] -> Flag a
    Flag [[Char]]
    names FlagInfo
    FlagNone Update a
    forall {p} {a}. p -> a -> Either a a
    upd [Char]
    "" [Char]
    help
        where upd :: p -> a -> Either a a
    upd p
    _ a
    x = a -> Either a a
    forall a b. b -> Either a b
    Right (a -> Either a a) -> a -> Either a a
    forall a b. (a -> b) -> a -> b
    $ a -> a
    f a
    x

    -- | Create a flag taking an optional argument value, with an optional value, a list of flag names,
    --   an update function, the type of the argument and some help text.
    flagOpt :: String -> [Name] -> Update a -> FlagHelp -> Help -> Flag a
    flagOpt :: forall a.
    [Char] -> [[Char]] -> Update a -> [Char] -> [Char] -> Flag a
    flagOpt [Char]
    def [[Char]]
    names Update a
    upd [Char]
    typ [Char]
    help = [[Char]] -> FlagInfo -> Update a -> [Char] -> [Char] -> Flag a
    forall a.
    [[Char]] -> FlagInfo -> Update a -> [Char] -> [Char] -> Flag a
    Flag [[Char]]
    names ([Char] -> FlagInfo
    FlagOpt [Char]
    def) Update a
    upd [Char]
    typ [Char]
    help

    -- | Create a flag taking a required argument value, with a list of flag names,
    --   an update function, the type of the argument and some help text.
    flagReq :: [Name] -> Update a -> FlagHelp -> Help -> Flag a
    flagReq :: forall a. [[Char]] -> Update a -> [Char] -> [Char] -> Flag a
    flagReq [[Char]]
    names Update a
    upd [Char]
    typ [Char]
    help = [[Char]] -> FlagInfo -> Update a -> [Char] -> [Char] -> Flag a
    forall a.
    [[Char]] -> FlagInfo -> Update a -> [Char] -> [Char] -> Flag a
    Flag [[Char]]
    names FlagInfo
    FlagReq Update a
    upd [Char]
    typ [Char]
    help

    -- | Create an argument flag, with an update function and the type of the argument.
    flagArg :: Update a -> FlagHelp -> Arg a
    flagArg :: forall a. Update a -> [Char] -> Arg a
    flagArg Update a
    upd [Char]
    typ = Update a -> [Char] -> Bool -> Arg a
    forall a. Update a -> [Char] -> Bool -> Arg a
    Arg Update a
    upd [Char]
    typ Bool
    False

    -- | Create a boolean flag, with a list of flag names, an update function and some help text.
    flagBool :: [Name] -> (Bool -> a -> a) -> Help -> Flag a
    flagBool :: forall a. [[Char]] -> (Bool -> a -> a) -> [Char] -> Flag a
    flagBool [[Char]]
    names Bool -> a -> a
    f [Char]
    help = [[Char]] -> FlagInfo -> Update a -> [Char] -> [Char] -> Flag a
    forall a.
    [[Char]] -> FlagInfo -> Update a -> [Char] -> [Char] -> Flag a
    Flag [[Char]]
    names ([Char] -> FlagInfo
    FlagOptRare [Char]
    "") Update a
    upd [Char]
    "" [Char]
    help
        where
            upd :: Update a
    upd [Char]
    s a
    x = case if [Char]
    s [Char] -> [Char] -> Bool
    forall a. Eq a => a -> a -> Bool
    == [Char]
    "" then Bool -> Maybe Bool
    forall a. a -> Maybe a
    Just Bool
    True else [Char] -> Maybe Bool
    parseBool [Char]
    s of
                Just Bool
    b -> a -> Either [Char] a
    forall a b. b -> Either a b
    Right (a -> Either [Char] a) -> a -> Either [Char] a
    forall a b. (a -> b) -> a -> b
    $ Bool -> a -> a
    f Bool
    b a
    x
                Maybe Bool
    Nothing -> [Char] -> Either [Char] a
    forall a b. a -> Either a b
    Left [Char]
    "expected boolean value (true/false)"