descriptive 0.5.0 → 0.6.0
raw patch · 5 files changed
+58/−30 lines, 5 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
- Descriptive.Form: validate :: Text -> (a -> Maybe b) -> Consumer (Map Text Text) Form a -> Consumer (Map Text Text) Form b
+ Descriptive: validate :: d -> (forall m. MonadState s m => a -> m (Maybe b)) -> Consumer s d a -> Consumer s d b
Files
- README.md +26/−0
- descriptive.cabal +1/−1
- src/Descriptive.hs +25/−1
- src/Descriptive/Form.hs +1/−23
- src/test/Main.hs +5/−5
README.md view
@@ -20,6 +20,8 @@ data Consumer s d a ``` +## Making descriptive consumers+ To make a consumer, this combinator is used: ``` haskell@@ -37,12 +39,15 @@ 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+ To use a consumer or describe what it does, these are used: ``` haskell consume :: Consumer s d a -- ^ The consumer to run. -> s -- ^ Initial state. -> Result (Description d) a+ describe :: Consumer s d a -- ^ The consumer to run. -> s -- ^ Initial state. Can be \"empty\" if you don't use it for -- generating descriptions.@@ -56,12 +61,15 @@ => Consumer s d a -- ^ The consumer to run. -> StateT s m (Result (Description d) a) runConsumer (Consumer _ m) = m+ runDescription :: Monad m => Consumer s d a -- ^ The consumer to run. -> StateT s m (Description d) runDescription (Consumer desc _) = desc ``` +## Descriptions+ A description is like this: ``` haskell@@ -85,6 +93,24 @@ describeParser :: Description Text -> Text describeForm :: Description (Html ()) -> Html () describeArgs :: Description CmdArgs -> Text+```++## 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+validation, things of that nature:++``` haskell+wrap :: (forall m. Monad m => 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))+ -- ^ Transform the parser. Can re-run the parser as many times as desired.+ -> Consumer t d a+ -> Consumer s d b ``` See below for some examples of this library.
descriptive.cabal view
@@ -1,5 +1,5 @@ name: descriptive-version: 0.5.0+version: 0.6.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
@@ -21,7 +21,8 @@ ,Result(..) -- * Combinators ,consumer- ,wrap)+ ,wrap+ ,validate) where import Control.Applicative@@ -267,3 +268,26 @@ 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 d' check =+ wrap (liftM wrapper)+ (\d p ->+ do s <- get+ r <- p+ case r of+ (Failed e) -> return (Failed e)+ (Continued e) ->+ return (Continued (wrapper e))+ (Succeeded a) ->+ do r' <- check a+ case r' of+ Nothing ->+ do doc <- withStateT (const s) d+ return (Continued (wrapper doc))+ Just a' -> return (Succeeded a'))+ where wrapper = Wrap d'
src/Descriptive/Form.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE RankNTypes #-} {-# LANGUAGE TupleSections #-} {-# LANGUAGE FlexibleContexts #-} @@ -6,7 +7,6 @@ module Descriptive.Form (-- * Combinators input- ,validate -- * Description ,Form (..) )@@ -34,25 +34,3 @@ Nothing -> Continued d Just a -> Succeeded a)) where d = Unit (Input name)---- | Validate a form input with a description of what's required.-validate :: Text -- ^ Description of what it expects.- -> (a -> Maybe b) -- ^ Attempt to parse the value.- -> Consumer (Map Text Text) Form a -- ^ Consumer to add validation to.- -> Consumer (Map Text Text) Form b-validate d' check =- wrap (liftM wrapper)- (\d p ->- do s <- get- r <- p- case r of- (Failed e) -> return (Failed e)- (Continued e) ->- return (Continued (wrapper e))- (Succeeded a) ->- case check a of- Nothing ->- do doc <- withStateT (const s) d- return (Continued (wrapper doc))- Just a' -> return (Succeeded a'))- where wrapper = Wrap (Constraint d')
src/test/Main.hs view
@@ -94,12 +94,12 @@ [("password2","gob"),("password","go"),("token","woot")]) == Succeeded "woot") where login =- Form.validate- "confirmed password (entered the same twice)"+ validate+ (Form.Constraint "confirmed password (entered the same twice)") (\(x,y) ->- if x == y- then Just y- else Nothing)+ return (if x == y+ then Just y+ else Nothing)) ((,) <$> Form.input "password" <*> Form.input "password2") <|>