descriptive 0.6.0 → 0.7.0
raw patch · 9 files changed
+106/−76 lines, 9 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
- Descriptive: instance Alternative (Consumer s d)
- Descriptive: instance Applicative (Consumer s d)
- Descriptive: instance Functor (Consumer s d)
- Descriptive: instance Monoid a => Monoid (Consumer s d a)
+ Descriptive: instance (Monoid a, Monad m) => Monoid (Consumer s d m a)
+ Descriptive: instance Monad m => Alternative (Consumer s d m)
+ Descriptive: instance Monad m => Applicative (Consumer s d m)
+ Descriptive: instance Monad m => Functor (Consumer s d m)
- Descriptive: Consumer :: (forall m. Monad m => StateT s m (Description d)) -> (forall m. Monad m => StateT s m (Result (Description d) a)) -> Consumer s d a
+ Descriptive: Consumer :: StateT s m (Description d) -> StateT s m (Result (Description d) a) -> Consumer s d m a
- Descriptive: consume :: Consumer s d a -> s -> Result (Description d) a
+ Descriptive: consume :: Consumer s d Identity a -> s -> Result (Description d) a
- Descriptive: consumer :: (forall m. Monad m => StateT s m (Description d)) -> (forall m. Monad m => StateT s m (Result (Description d) a)) -> Consumer s d a
+ Descriptive: consumer :: (StateT s m (Description d)) -> (StateT s m (Result (Description d) a)) -> Consumer s d m a
- Descriptive: consumerDesc :: Consumer s d a -> forall m. Monad m => StateT s m (Description d)
+ Descriptive: consumerDesc :: Consumer s d m a -> StateT s m (Description d)
- Descriptive: consumerParse :: Consumer s d a -> forall m. Monad m => StateT s m (Result (Description d) a)
+ Descriptive: consumerParse :: Consumer s d m a -> StateT s m (Result (Description d) a)
- Descriptive: data Consumer s d a
+ Descriptive: data Consumer s d m a
- Descriptive: describe :: Consumer s d a -> s -> Description d
+ Descriptive: describe :: Consumer s d Identity a -> s -> Description d
- Descriptive: runConsumer :: Monad m => Consumer s d a -> StateT s m (Result (Description d) a)
+ Descriptive: runConsumer :: Monad m => Consumer s d m a -> StateT s m (Result (Description d) a)
- Descriptive: runDescription :: Monad m => Consumer s d a -> StateT s m (Description d)
+ Descriptive: runDescription :: Monad m => Consumer s d m a -> StateT s m (Description d)
- Descriptive: validate :: d -> (forall m. MonadState s m => a -> m (Maybe b)) -> Consumer s d a -> Consumer s d b
+ Descriptive: validate :: Monad m => d -> (a -> StateT s m (Maybe b)) -> Consumer s d m a -> Consumer s d m b
- Descriptive: wrap :: (forall m. Monad m => StateT t m (Description d) -> StateT s m (Description d)) -> (forall m. Monad m => StateT t m (Description d) -> StateT t m (Result (Description d) a) -> StateT s m (Result (Description d) b)) -> Consumer t d a -> Consumer s d b
+ Descriptive: wrap :: (StateT t m (Description d) -> StateT s m (Description d)) -> (StateT t m (Description d) -> StateT t m (Result (Description d) a) -> StateT s m (Result (Description d) b)) -> Consumer t d m a -> Consumer s d m b
- Descriptive.Char: anyChar :: Consumer [Char] Text Char
+ Descriptive.Char: anyChar :: Monad m => Consumer [Char] Text m Char
- Descriptive.Char: char :: Char -> Consumer [Char] Text Char
+ Descriptive.Char: char :: Monad m => Char -> Consumer [Char] Text m Char
- Descriptive.Char: string :: [Char] -> Consumer [Char] Text [Char]
+ Descriptive.Char: string :: Monad m => [Char] -> Consumer [Char] Text m [Char]
- Descriptive.Form: input :: Text -> Consumer (Map Text Text) Form Text
+ Descriptive.Form: input :: Monad m => Text -> Consumer (Map Text Text) Form m Text
- Descriptive.Formlet: indexed :: Consumer FormletState Formlet Text
+ Descriptive.Formlet: indexed :: Monad m => Consumer FormletState Formlet m Text
- Descriptive.JSON: array :: Text -> Consumer Value Doc a -> Consumer Value Doc (Vector a)
+ Descriptive.JSON: array :: Monad m => Text -> Consumer Value Doc m a -> Consumer Value Doc m (Vector a)
- Descriptive.JSON: bool :: Text -> Consumer Value Doc Bool
+ Descriptive.JSON: bool :: Monad m => Text -> Consumer Value Doc m Bool
- Descriptive.JSON: double :: Text -> Consumer Value Doc Double
+ Descriptive.JSON: double :: Monad m => Text -> Consumer Value Doc m Double
- Descriptive.JSON: info :: Text -> Consumer s Doc a -> Consumer s Doc a
+ Descriptive.JSON: info :: Monad m => Text -> Consumer s Doc m a -> Consumer s Doc m a
- Descriptive.JSON: integer :: Text -> Consumer Value Doc Integer
+ Descriptive.JSON: integer :: Monad m => Text -> Consumer Value Doc m Integer
- Descriptive.JSON: key :: Text -> Consumer Value Doc a -> Consumer Object Doc a
+ Descriptive.JSON: key :: Monad m => Text -> Consumer Value Doc m a -> Consumer Object Doc m a
- Descriptive.JSON: keyMaybe :: Text -> Consumer Value Doc a -> Consumer Object Doc (Maybe a)
+ Descriptive.JSON: keyMaybe :: Monad m => Text -> Consumer Value Doc m a -> Consumer Object Doc m (Maybe a)
- Descriptive.JSON: label :: Text -> Consumer s Doc a -> Consumer s Doc a
+ Descriptive.JSON: label :: Monad m => Text -> Consumer s Doc m a -> Consumer s Doc m a
- Descriptive.JSON: null :: Text -> Consumer Value Doc ()
+ Descriptive.JSON: null :: Monad m => Text -> Consumer Value Doc m ()
- Descriptive.JSON: object :: Text -> Consumer Object Doc a -> Consumer Value Doc a
+ Descriptive.JSON: object :: Monad m => Text -> Consumer Object Doc m a -> Consumer Value Doc m a
- Descriptive.JSON: string :: Text -> Consumer Value Doc Text
+ Descriptive.JSON: string :: Monad m => Text -> Consumer Value Doc m Text
- Descriptive.Options: anyString :: Text -> Consumer [Text] (Option a) Text
+ Descriptive.Options: anyString :: Monad m => Text -> Consumer [Text] (Option a) m Text
- Descriptive.Options: arg :: Text -> Text -> Consumer [Text] (Option a) Text
+ Descriptive.Options: arg :: Monad m => Text -> Text -> Consumer [Text] (Option a) m Text
- Descriptive.Options: constant :: Text -> Text -> v -> Consumer [Text] (Option a) v
+ Descriptive.Options: constant :: Monad m => Text -> Text -> v -> Consumer [Text] (Option a) m v
- Descriptive.Options: flag :: Text -> Text -> v -> Consumer [Text] (Option a) v
+ Descriptive.Options: flag :: Monad m => Text -> Text -> v -> Consumer [Text] (Option a) m v
- Descriptive.Options: prefix :: Text -> Text -> Consumer [Text] (Option a) Text
+ Descriptive.Options: prefix :: Monad m => Text -> Text -> Consumer [Text] (Option a) m Text
- Descriptive.Options: stop :: Consumer [Text] (Option a) a -> Consumer [Text] (Option a) ()
+ Descriptive.Options: stop :: Monad m => Consumer [Text] (Option a) m a -> Consumer [Text] (Option a) m ()
- Descriptive.Options: switch :: Text -> Text -> Consumer [Text] (Option a) Bool
+ Descriptive.Options: switch :: Monad m => Text -> Text -> Consumer [Text] (Option a) m Bool
Files
- README.md +14/−4
- descriptive.cabal +1/−1
- src/Descriptive.hs +25/−23
- src/Descriptive/Char.hs +3/−3
- src/Descriptive/Form.hs +1/−1
- src/Descriptive/Formlet.hs +1/−1
- src/Descriptive/JSON.hs +39/−28
- src/Descriptive/Options.hs +21/−14
- src/test/Main.hs +1/−1
README.md view
@@ -20,7 +20,7 @@ data Consumer s d a ``` -## Making descriptive consumers+### Making descriptive consumers To make a consumer, this combinator is used: @@ -39,7 +39,7 @@ strings, a Map, a Vector, etc. You may or may not decide to modify the state during generation of the description and during parsing. -## Running descriptive consumers+### Running descriptive consumers To use a consumer or describe what it does, these are used: @@ -68,7 +68,7 @@ runDescription (Consumer desc _) = desc ``` -## Descriptions+### Descriptions A description is like this: @@ -95,7 +95,7 @@ describeArgs :: Description CmdArgs -> Text ``` -## Wrapping+### Wrapping One can wrap up a consumer to alter either the description or the parser or both, this can be used for wrapping labels, or adding@@ -111,6 +111,16 @@ -- ^ Transform the parser. Can re-run the parser as many times as desired. -> Consumer t d a -> Consumer s d b+```++There is also a handy function written in terms of `wrap` which will+validate a consumer.++``` haskell+validate :: d -- ^ Description of what it expects.+ -> (forall m. MonadState s m => a -> m (Maybe b)) -- ^ Attempt to parse the value.+ -> Consumer s d a -- ^ Consumer to add validation to.+ -> Consumer s d b -- ^ A new validating consumer. ``` See below for some examples of this library.
descriptive.cabal view
@@ -1,5 +1,5 @@ name: descriptive-version: 0.6.0+version: 0.7.0 synopsis: Self-describing consumers/parsers; forms, cmd-line args, JSON, etc. description: Self-describing consumers/parsers. See the README.md for more information. It is currently EXPERIMENTAL. stability: Experimental
src/Descriptive.hs view
@@ -27,6 +27,7 @@ import Control.Applicative import Control.Monad.State.Strict+import Control.Monad.Identity import Data.Bifunctor import Data.Monoid @@ -34,13 +35,13 @@ -- Running -- | Run a consumer.-consume :: Consumer s d a -- ^ The consumer to run.+consume :: Consumer s d Identity a -- ^ The consumer to run. -> s -- ^ Initial state. -> Result (Description d) a consume c s = evalState (runConsumer c) s -- | Describe a consumer.-describe :: Consumer s d a -- ^ The consumer to run.+describe :: Consumer s d Identity a -- ^ The consumer to run. -> s -- ^ Initial state. Can be \"empty\" if you don't use it for -- generating descriptions. -> Description d -- ^ A description and resultant state.@@ -48,13 +49,13 @@ -- | Run a consumer. runConsumer :: Monad m- => Consumer s d a -- ^ The consumer to run.+ => Consumer s d m a -- ^ The consumer to run. -> StateT s m (Result (Description d) a) runConsumer (Consumer _ m) = m -- | Describe a consumer. runDescription :: Monad m- => Consumer s d a -- ^ The consumer to run.+ => Consumer s d m a -- ^ The consumer to run. -> StateT s m (Description d) -- ^ A description and resultant state. runDescription (Consumer desc _) = desc @@ -83,9 +84,9 @@ deriving (Show,Eq) -- | A consumer.-data Consumer s d a =- Consumer {consumerDesc :: forall m. Monad m => StateT s m (Description d)- ,consumerParse :: forall m. Monad m => StateT s m (Result (Description d) a)}+data Consumer s d m a =+ Consumer {consumerDesc :: StateT s m (Description d)+ ,consumerParse :: StateT s m (Result (Description d) a)} -- | Some result. data Result e a@@ -106,7 +107,7 @@ Failed e -> Failed (f e) Continued e -> Continued (f e) -instance Functor (Consumer s d) where+instance Monad m => Functor (Consumer s d m) where fmap f (Consumer d p) = Consumer d (do r <- p@@ -118,7 +119,7 @@ (Succeeded a) -> return (Succeeded (f a))) -instance Applicative (Consumer s d) where+instance Monad m => Applicative (Consumer s d m) where pure a = consumer (return mempty) (return (Succeeded a))@@ -150,7 +151,7 @@ Succeeded a -> return (Succeeded (f a))) -instance Alternative (Consumer s d) where+instance Monad m => Alternative (Consumer s d m) where empty = consumer (return mempty) (return (Failed mempty))@@ -186,7 +187,7 @@ -- | An internal sequence maker which describes itself better than -- regular Alternative, and is strict, not lazy.-sequenceHelper :: Integer -> Consumer t d a -> Consumer t d [a]+sequenceHelper :: Monad m => Integer -> Consumer t d m a -> Consumer t d m [a] sequenceHelper minb = wrap (liftM redescribe) (\_ p ->@@ -238,7 +239,7 @@ Continued e -> Continued e Succeeded b -> Succeeded (a <> b) -instance (Monoid a) => Monoid (Consumer s d a) where+instance (Monoid a, Monad m) => Monoid (Consumer s d m a) where mempty = consumer (return mempty) (return mempty)@@ -248,32 +249,33 @@ -- Combinators -- | Make a self-describing consumer.-consumer :: (forall m. Monad m => StateT s m (Description d))+consumer :: (StateT s m (Description d)) -- ^ Produce description based on the state.- -> (forall m. Monad m => StateT s m (Result (Description d) a))+ -> (StateT s m (Result (Description d) a)) -- ^ Parse the state and maybe transform it if desired.- -> Consumer s d a+ -> Consumer s d m a consumer d p = Consumer d p -- | Wrap a consumer with another consumer. The type looks more -- intimidating than it actually is. The source code is trivial. It -- simply allows for a way to transform the type of the state.-wrap :: (forall m. Monad m => StateT t m (Description d) -> StateT s m (Description d))+wrap :: (StateT t m (Description d) -> StateT s m (Description d)) -- ^ Transform the description.- -> (forall m. Monad m => StateT t m (Description d) -> StateT t m (Result (Description d) a) -> StateT s m (Result (Description d) b))+ -> (StateT t m (Description d) -> StateT t m (Result (Description d) a) -> StateT s m (Result (Description d) b)) -- ^ Transform the parser. Can re-run the parser as many times as desired.- -> Consumer t d a- -> Consumer s d b+ -> Consumer t d m a+ -> Consumer s d m b wrap redescribe reparse (Consumer d p) = Consumer (redescribe d) (reparse d p) -- | Add validation to a consumer.-validate :: d -- ^ Description of what it expects.- -> (forall m. MonadState s m => a -> m (Maybe b)) -- ^ Attempt to parse the value.- -> Consumer s d a -- ^ Consumer to add validation to.- -> Consumer s d b -- ^ A new validating consumer.+validate :: Monad m + => d -- ^ Description of what it expects.+ -> (a -> StateT s m (Maybe b)) -- ^ Attempt to parse the value.+ -> Consumer s d m a -- ^ Consumer to add validation to.+ -> Consumer s d m b -- ^ A new validating consumer. validate d' check = wrap (liftM wrapper) (\d p ->
src/Descriptive/Char.hs view
@@ -14,7 +14,7 @@ import qualified Data.Text as T -- | Consume any character.-anyChar :: Consumer [Char] Text Char+anyChar :: Monad m => Consumer [Char] Text m Char anyChar = consumer (return d) (do s <- get@@ -25,7 +25,7 @@ where d = Unit "a character" -- | A character consumer.-char :: Char -> Consumer [Char] Text Char+char :: Monad m => Char -> Consumer [Char] Text m Char char c = wrap (liftM (const d)) (\_ p ->@@ -41,7 +41,7 @@ where d = Unit (T.singleton c) -- | A string consumer.-string :: [Char] -> Consumer [Char] Text [Char]+string :: Monad m => [Char] -> Consumer [Char] Text m [Char] string = wrap (liftM (Sequence . flattenAnds)) (\_ p -> p) .
src/Descriptive/Form.hs view
@@ -26,7 +26,7 @@ deriving (Show,Eq) -- | Consume any input value.-input :: Text -> Consumer (Map Text Text) Form Text+input :: Monad m => Text -> Consumer (Map Text Text) Form m Text input name = consumer (return d) (do s <- get
src/Descriptive/Formlet.hs view
@@ -31,7 +31,7 @@ deriving (Show,Eq) -- | Consume any character.-indexed :: Consumer FormletState Formlet Text+indexed :: Monad m => Consumer FormletState Formlet m Text indexed = consumer (do i <- nextIndex return (d i))
src/Descriptive/JSON.hs view
@@ -62,9 +62,10 @@ deriving (Eq,Show,Typeable,Data) -- | Consume an object.-object :: Text -- ^ Description of what the object is.- -> Consumer Object Doc a -- ^ An object consumer.- -> Consumer Value Doc a+object :: Monad m+ => Text -- ^ Description of what the object is.+ -> Consumer Object Doc m a -- ^ An object consumer.+ -> Consumer Value Doc m a object desc = wrap (\d -> do s <- get@@ -92,9 +93,10 @@ where doc = Object desc -- | Consume from object at the given key.-key :: Text -- ^ The key to lookup.- -> Consumer Value Doc a -- ^ A value consumer of the object at the key.- -> Consumer Object Doc a+key :: Monad m+ => Text -- ^ The key to lookup.+ -> Consumer Value Doc m a -- ^ A value consumer of the object at the key.+ -> Consumer Object Doc m a key k = wrap (\d -> do s <- get@@ -117,9 +119,10 @@ -- | Optionally consume from object at the given key, only if it -- exists.-keyMaybe :: Text -- ^ The key to lookup.- -> Consumer Value Doc a -- ^ A value consumer of the object at the key.- -> Consumer Object Doc (Maybe a)+keyMaybe :: Monad m+ => Text -- ^ The key to lookup.+ -> Consumer Value Doc m a -- ^ A value consumer of the object at the key.+ -> Consumer Object Doc m (Maybe a) keyMaybe k = wrap (\d -> do s <- get@@ -141,9 +144,10 @@ where doc = Key k -- | Consume an array.-array :: Text -- ^ Description of this array.- -> Consumer Value Doc a -- ^ Consumer for each element in the array.- -> Consumer Value Doc (Vector a)+array :: Monad m+ => Text -- ^ Description of this array.+ -> Consumer Value Doc m a -- ^ Consumer for each element in the array.+ -> Consumer Value Doc m (Vector a) array desc = wrap (\d -> liftM (Wrap doc) d) (\_ p ->@@ -172,8 +176,9 @@ where doc = Array desc -- | Consume a string.-string :: Text -- ^ Description of what the string is for.- -> Consumer Value Doc Text+string :: Monad m+ => Text -- ^ Description of what the string is for.+ -> Consumer Value Doc m Text string doc = consumer (return d) (do s <- get@@ -184,8 +189,9 @@ where d = Unit (Text doc) -- | Consume an integer.-integer :: Text -- ^ Description of what the integer is for.- -> Consumer Value Doc Integer+integer :: Monad m+ => Text -- ^ Description of what the integer is for.+ -> Consumer Value Doc m Integer integer doc = consumer (return d) (do s <- get@@ -197,8 +203,9 @@ where d = Unit (Integer doc) -- | Consume an double.-double :: Text -- ^ Description of what the double is for.- -> Consumer Value Doc Double+double :: Monad m+ => Text -- ^ Description of what the double is for.+ -> Consumer Value Doc m Double double doc = consumer (return d) (do s <- get@@ -209,8 +216,9 @@ where d = Unit (Double doc) -- | Parse a boolean.-bool :: Text -- ^ Description of what the bool is for.- -> Consumer Value Doc Bool+bool :: Monad m+ => Text -- ^ Description of what the bool is for.+ -> Consumer Value Doc m Bool bool doc = consumer (return d) (do s <- get@@ -221,8 +229,9 @@ where d = Unit (Boolean doc) -- | Expect null.-null :: Text -- ^ What the null is for.- -> Consumer Value Doc ()+null :: Monad m+ => Text -- ^ What the null is for.+ -> Consumer Value Doc m () null doc = consumer (return d) (do s <- get@@ -233,9 +242,10 @@ where d = Unit (Null doc) -- | Wrap a consumer with a label e.g. a type tag.-label :: Text -- ^ Some label.- -> Consumer s Doc a -- ^ A value consumer.- -> Consumer s Doc a+label :: Monad m+ => Text -- ^ Some label.+ -> Consumer s Doc m a -- ^ A value consumer.+ -> Consumer s Doc m a label desc = wrap (liftM (Wrap doc)) (\_ p ->@@ -247,9 +257,10 @@ where doc = Label desc -- | Wrap a consumer with some handy information.-info :: Text -- ^ Some information.- -> Consumer s Doc a -- ^ A value consumer.- -> Consumer s Doc a+info :: Monad m+ => Text -- ^ Some information.+ -> Consumer s Doc m a -- ^ A value consumer.+ -> Consumer s Doc m a info desc = wrap (liftM (Wrap doc)) (\_ p ->
src/Descriptive/Options.hs view
@@ -46,9 +46,10 @@ -- | If the consumer succeeds, stops the whole parser and returns -- 'Stopped' immediately.-stop :: Consumer [Text] (Option a) a+stop :: Monad m+ => Consumer [Text] (Option a) m a -- ^ A parser which, when it succeeds, causes the whole parser to stop.- -> Consumer [Text] (Option a) ()+ -> Consumer [Text] (Option a) m () stop = wrap (liftM (Wrap Stops)) (\d p ->@@ -66,8 +67,9 @@ -- | Consume one argument from the argument list and pops it from the -- start of the list.-anyString :: Text -- Help for the string.- -> Consumer [Text] (Option a) Text+anyString :: Monad m+ => Text -- Help for the string.+ -> Consumer [Text] (Option a) m Text anyString help = consumer (return d) (do s <- get@@ -79,10 +81,11 @@ -- | Consume one argument from the argument list which must match the -- given string, and also pops it off the argument list.-constant :: Text -- ^ String.+constant :: Monad m+ => Text -- ^ String. -> Text -- ^ Description. -> v- -> Consumer [Text] (Option a) v+ -> Consumer [Text] (Option a) m v constant x' desc v = consumer (return d) (do s <- get@@ -95,10 +98,11 @@ -- | Find a value flag which must succeed. Removes it from the -- argument list if it succeeds.-flag :: Text -- ^ Name.+flag :: Monad m+ => Text -- ^ Name. -> Text -- ^ Description. -> v -- ^ Value returned when present.- -> Consumer [Text] (Option a) v+ -> Consumer [Text] (Option a) m v flag name help v = consumer (return d) (do s <- get@@ -110,18 +114,20 @@ -- | Find a boolean flag. Always succeeds. Omission counts as -- 'False'. Removes it from the argument list if it returns True.-switch :: Text -- ^ Name.+switch :: Monad m+ => Text -- ^ Name. -> Text -- ^ Description.- -> Consumer [Text] (Option a) Bool+ -> Consumer [Text] (Option a) m Bool switch name help = flag name help True <|> pure False -- | Find an argument prefixed by -X. Removes it from the argument -- list when it succeeds.-prefix :: Text -- ^ Prefix string.+prefix :: Monad m+ => Text -- ^ Prefix string. -> Text -- ^ Description.- -> Consumer [Text] (Option a) Text+ -> Consumer [Text] (Option a) m Text prefix pref help = consumer (return d) (do s <- get@@ -133,9 +139,10 @@ -- | Find a named argument e.g. @--name value@. Removes it from the -- argument list when it succeeds.-arg :: Text -- ^ Name.+arg :: Monad m+ => Text -- ^ Name. -> Text -- ^ Description.- -> Consumer [Text] (Option a) Text+ -> Consumer [Text] (Option a) m Text arg name help = consumer (return d) (do s <- get
src/test/Main.hs view
@@ -164,7 +164,7 @@ ,submissionSubreddit :: !Integer} deriving (Show,Eq) -submission :: Consumer Value JSON.Doc Submission+submission :: Monad m => Consumer Value JSON.Doc m Submission submission = JSON.object "Submission" (Submission