-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | ditto is a type-safe HTML form generation and validation library -- -- ditto follows in the footsteps of formlets and digestive-functors -- <= 0.2. It provides a type-safe and composable method for -- generating an HTML form that includes validation. @package ditto @version 0.4 -- | Types relevant to forms and their validation. module Ditto.Types -- | An ID used to identify forms data FormId FormId :: {-# UNPACK #-} !Text -> {-# UNPACK #-} !NonEmpty Int -> FormId FormIdName :: {-# UNPACK #-} !Text -> {-# UNPACK #-} !Int -> FormId -- | A range of ID's to specify a group of forms data FormRange FormRange :: FormId -> FormId -> FormRange -- | Encoding a FormId: use this instead of show for the -- name of the input / query string parameter encodeFormId :: FormId -> Text -- | get the head Int from a FormId formIdentifier :: FormId -> Int -- | used to represent whether a value was found in the form submission -- data, missing from the form submission data, or expected that the -- default value should be used data Value a Default :: Value a Missing :: Value a Found :: a -> Value a -- | views, values as a result of the environment, etc. -- -- Function which creates the form view newtype View err v View :: ([(FormRange, err)] -> v) -> View err v [unView] :: View err v -> [(FormRange, err)] -> v -- | Proved records a value, the location that value came from, and -- something that was proved about the value. data Proved a Proved :: FormRange -> a -> Proved a [pos] :: Proved a -> FormRange [unProved] :: Proved a -> a -- | Type for failing computations Similar to Either but with an -- accumilating Applicative instance data Result e ok Error :: [(FormRange, e)] -> Result e ok Ok :: ok -> Result e ok instance Data.Traversable.Traversable Ditto.Types.Proved instance Data.Foldable.Foldable Ditto.Types.Proved instance GHC.Base.Functor Ditto.Types.Proved instance GHC.Show.Show a => GHC.Show.Show (Ditto.Types.Proved a) instance Data.Traversable.Traversable (Ditto.Types.Result e) instance Data.Foldable.Foldable (Ditto.Types.Result e) instance GHC.Base.Functor (Ditto.Types.Result e) instance (GHC.Classes.Eq e, GHC.Classes.Eq ok) => GHC.Classes.Eq (Ditto.Types.Result e ok) instance (GHC.Show.Show e, GHC.Show.Show ok) => GHC.Show.Show (Ditto.Types.Result e ok) instance Data.Foldable.Foldable Ditto.Types.Value instance Data.Traversable.Traversable Ditto.Types.Value instance GHC.Base.Functor Ditto.Types.Value instance GHC.Show.Show a => GHC.Show.Show (Ditto.Types.Value a) instance GHC.Classes.Eq a => GHC.Classes.Eq (Ditto.Types.Value a) instance GHC.Base.Functor (Ditto.Types.View err) instance GHC.Base.Monoid v => GHC.Base.Monoid (Ditto.Types.View err v) instance GHC.Base.Semigroup v => GHC.Base.Semigroup (Ditto.Types.View err v) instance GHC.Show.Show Ditto.Types.FormRange instance GHC.Classes.Eq Ditto.Types.FormRange instance GHC.Show.Show Ditto.Types.FormId instance GHC.Classes.Ord Ditto.Types.FormId instance GHC.Classes.Eq Ditto.Types.FormId instance GHC.Base.Monad (Ditto.Types.Result e) instance GHC.Base.Applicative (Ditto.Types.Result e) instance GHC.Base.Applicative Ditto.Types.Value instance GHC.Base.Alternative Ditto.Types.Value instance GHC.Base.Semigroup a => GHC.Base.Semigroup (Ditto.Types.Value a) instance Data.String.IsString Ditto.Types.FormId instance Torsor.Torsor Ditto.Types.FormId GHC.Types.Int -- | This module contains two classes. FormInput is a class which is -- parameterized over the input type used to represent form data -- in different web frameworks. There should be one instance for each -- framework, such as Happstack, Snap, WAI, etc. -- -- The FormError class is used to map error messages into an -- application specific error type. module Ditto.Backend -- | an error type used to represent errors that are common to all backends -- -- These errors should only occur if there is a bug in the ditto-* -- packages. Perhaps we should make them an Exception so that we -- can get rid of the FormError class. data CommonFormError input InputMissing :: FormId -> CommonFormError input NoStringFound :: input -> CommonFormError input NoFileFound :: input -> CommonFormError input MultiFilesFound :: input -> CommonFormError input MultiStringsFound :: input -> CommonFormError input MissingDefaultValue :: CommonFormError input -- | some default error messages for CommonFormError commonFormErrorStr :: (input -> String) -> CommonFormError input -> String -- | some default error messages for CommonFormError commonFormErrorText :: (input -> Text) -> CommonFormError input -> Text -- | A Class to lift a CommonFormError into an application-specific -- error type class FormError input err commonFormError :: FormError input err => CommonFormError input -> err -- | Class which all backends should implement. class FormInput input where { -- | input is here the type that is used to represent a value -- uploaded by the client in the request. type family FileType input; } -- | Parse the input into a string. This is used for simple text fields -- among other things getInputString :: (FormInput input, FormError input err) => input -> Either err String getInputStrings :: FormInput input => input -> [String] -- | Parse the input value into Text getInputText :: (FormInput input, FormError input err) => input -> Either err Text getInputTexts :: FormInput input => input -> [Text] -- | Get a file descriptor for an uploaded file getInputFile :: (FormInput input, FormError input err) => input -> Either err (FileType input) instance GHC.Show.Show input => GHC.Show.Show (Ditto.Backend.CommonFormError input) instance GHC.Classes.Ord input => GHC.Classes.Ord (Ditto.Backend.CommonFormError input) instance GHC.Classes.Eq input => GHC.Classes.Eq (Ditto.Backend.CommonFormError input) instance Ditto.Backend.FormError Data.Text.Internal.Text Data.Text.Internal.Text -- | The core module for ditto. -- -- This module provides the Form type and helper functions for -- constructing typesafe forms inside arbitrary "views" / web frameworks. -- ditto is meant to be a generalized formlet library used to -- write formlet libraries specific to a web / gui framework module Ditto.Core -- | The Form's state is just the range of identifiers so far type FormState m = StateT FormRange m -- | ditto's representation of a formlet data Form m input err view a Form :: (input -> m (Either err a)) -> m a -> FormState m (View err view, Result err (Proved a)) -> Form m input err view a -- | Decode the value from the input [formDecodeInput] :: Form m input err view a -> input -> m (Either err a) -- | The initial value [formInitialValue] :: Form m input err view a -> m a -- | A FormState which produced a View and a -- Result [formFormlet] :: Form m input err view a -> FormState m (View err view, Result err (Proved a)) -- | The environment typeclass: the interface between ditto and a given -- framework class Monad m => Environment m input | m -> input environment :: Environment m input => FormId -> m (Value input) -- | Run the form, but always return the initial value newtype NoEnvironment input m a NoEnvironment :: m a -> NoEnvironment input m a [getNoEnvironment] :: NoEnvironment input m a -> m a -- | Run the form, but with a given environment function newtype WithEnvironment input m a WithEnvironment :: ReaderT (FormId -> m (Value input)) m a -> WithEnvironment input m a [getWithEnvironment] :: WithEnvironment input m a -> ReaderT (FormId -> m (Value input)) m a -- | environment which will always return the initial value noEnvironment :: Applicative m => FormId -> m (Value input) -- | infix mapView: succinctly mix the view dsl and the formlets -- dsl foo @$ do .. (@$) :: Monad m => (view -> view') -> Form m input err view a -> Form m input err view' a infixr 0 @$ -- | Catch errors purely catchFormError :: Monad m => ([err] -> a) -> Form m input err view a -> Form m input err view a -- | Catch errors inside Form / m catchFormErrorM :: Monad m => Form m input err view a -> ([err] -> Form m input err view a) -> Form m input err view a -- | Evaluate a form -- -- Returns: -- -- eitherForm :: Monad m => Text -> Form m input err view a -> m (Either view a) -- | Get a FormId from the FormState getFormId :: Monad m => FormState m FormId -- | Utility function: Get the current input getFormInput :: Environment m input => FormState m (Value input) -- | Utility function: Gets the input of an arbitrary FormId. getFormInput' :: Environment m input => FormId -> FormState m (Value input) -- | Utility function: Get the current range getFormRange :: Monad m => FormState m FormRange -- | Get a FormIdName from the FormState getNamedFormId :: Monad m => Text -> FormState m FormId -- | Increment a form ID incrementFormId :: FormId -> FormId -- | Check if a FormId is contained in a FormRange isInRange :: FormId -> FormRange -> Bool -- | Change the underlying Monad of the form, usually a lift or -- newtype mapFormMonad :: Monad f => (forall x. m x -> f x) -> Form m input err view a -> Form f input err view a -- | Map over the Result and View of a form mapResult :: Monad m => (Result err (Proved a) -> Result err (Proved a)) -> (View err view -> View err view) -> Form m input err view a -> Form m input err view a -- | Common operations on Forms -- -- Change the view of a form using a simple function -- -- This is useful for wrapping a form inside of a <fieldset> or -- other markup element. mapView :: Functor m => (view -> view') -> Form m input err view a -> Form m input err view' a -- | Utility Function: turn a view and pure value into a successful -- FormState mkOk :: Monad m => FormId -> view -> a -> FormState m (View err view, Result err (Proved a)) -- | Select the errors originating from this form or from any of the -- children of this form retainChildErrors :: FormRange -> [(FormRange, e)] -> [e] -- | Select the errors for a certain range retainErrors :: FormRange -> [(FormRange, e)] -> [e] -- | Run a form runForm :: Monad m => Text -> Form m input err view a -> m (View err view, Result err (Proved a)) -- | Run a form, and unwrap the result runForm_ :: Monad m => Text -> Form m input err view a -> m (view, Maybe a) -- | Always succeed decoding successDecode :: Applicative m => a -> input -> m (Either err a) -- | Turns a FormId into a FormRange by incrementing the -- base for the end Id unitRange :: FormId -> FormRange -- | Turn a view into a Form view :: Monad m => view -> Form m input err view () -- | Run the form with no environment, return only the html. This means -- that the values will always be their defaults viewForm :: Monad m => Text -> Form m input err view a -> m view -- | lift the result of a decoding to a Form pureRes :: (Monad m, Monoid view, FormError input err) => a -> Either err a -> Form m input err view a -- | Form is a MonadTrans, but we can't have an instance -- of it because of the order and kind of its type variables liftForm :: (Monad m, Monoid view) => m a -> Form m input err view a instance GHC.Base.Applicative m => GHC.Base.Applicative (Ditto.Core.WithEnvironment input m) instance GHC.Base.Functor m => GHC.Base.Functor (Ditto.Core.WithEnvironment input m) instance GHC.Base.Monad m => GHC.Base.Monad (Ditto.Core.WithEnvironment input m) instance GHC.Base.Applicative m => GHC.Base.Applicative (Ditto.Core.NoEnvironment input m) instance GHC.Base.Functor m => GHC.Base.Functor (Ditto.Core.NoEnvironment input m) instance GHC.Base.Monad m => GHC.Base.Monad (Ditto.Core.NoEnvironment input m) instance GHC.Base.Functor m => GHC.Base.Functor (Ditto.Core.Form m input err view) instance GHC.Base.Monad m => Control.Monad.Reader.Class.MonadReader (Ditto.Types.FormId -> m (Ditto.Types.Value input)) (Ditto.Core.WithEnvironment input m) instance Control.Monad.Trans.Class.MonadTrans (Ditto.Core.WithEnvironment input) instance GHC.Base.Monad m => Ditto.Core.Environment (Ditto.Core.WithEnvironment input m) input instance GHC.Base.Monad m => Ditto.Core.Environment (Ditto.Core.NoEnvironment input m) input instance (Ditto.Core.Environment m input, GHC.Base.Monoid view, Ditto.Backend.FormError input err) => GHC.Base.Monad (Ditto.Core.Form m input err view) instance (GHC.Base.Monad m, GHC.Base.Monoid view, Ditto.Backend.FormError input err, Ditto.Core.Environment m input) => GHC.Base.Alternative (Ditto.Core.Form m input err view) instance (GHC.Base.Monad m, GHC.Base.Monoid view) => GHC.Base.Applicative (Ditto.Core.Form m input err view) instance (GHC.Base.Monad m, GHC.Base.Monoid view, GHC.Base.Semigroup a) => GHC.Base.Semigroup (Ditto.Core.Form m input err view a) instance (GHC.Base.Monad m, GHC.Base.Monoid view, GHC.Base.Monoid a) => GHC.Base.Monoid (Ditto.Core.Form m input err view a) instance GHC.Base.Functor m => Data.Bifunctor.Bifunctor (Ditto.Core.Form m input err) -- | This module defines the Proof type, some proofs, and some -- helper functions. -- -- A Proof does three things: -- -- module Ditto.Proof -- | A Proof attempts to prove something about a value. -- -- If successful, it can also transform the value to a new value. The -- proof should hold for the new value as well. -- -- Generally, each Proof has a unique data-type associated with it -- which names the proof, such as: data Proof m err a b Proof :: (a -> m (Either err b)) -> (a -> b) -> Proof m err a b -- | function which provides the proof [proofFunction] :: Proof m err a b -> a -> m (Either err b) [proofNewInitialValue] :: Proof m err a b -> a -> b -- | apply a Proof to a Form prove :: (Monad m, Monoid view, FormError input error) => Form m input error view a -> Proof m error a b -> Form m input error view b -- | transform the Form result using a monadic Either -- function. transformEitherM :: (Monad m, Monoid view, FormError input error) => Form m input error view a -> (a -> m (Either error b)) -> (a -> b) -> Form m input error view b -- | transform the Form result using an Either function. transformEither :: (Monad m, Monoid view, FormError input error) => Form m input error view a -> (a -> Either error b) -> (a -> b) -> Form m input error view b -- | prove that a list is not empty notNullProof :: Monad m => error -> Proof m error [a] [a] -- | read an unsigned number in decimal notation decimal :: (Monad m, Eq i, Num i) => (String -> error) -> i -> Proof m error String i -- | read signed decimal number signedDecimal :: (Monad m, Eq i, Real i) => (String -> error) -> i -> Proof m error String i -- | read RealFrac number realFrac :: (Monad m, RealFrac a) => (String -> error) -> a -> Proof m error String a -- | read a signed RealFrac number realFracSigned :: (Monad m, RealFrac a) => (String -> error) -> a -> Proof m error String a -- | This module provides helper functions for HTML input elements. These -- helper functions are not specific to any particular web framework or -- html library. -- -- Additionally, the inputs generated with the functions from this module -- will have their names/ids automatically enumerated. -- -- For named formlets, see Ditto.Generalized.Named module Ditto.Generalized.Unnamed -- | a choice for inputChoice data Choice lbl a Choice :: FormId -> lbl -> Bool -> a -> Choice lbl a -- | the formId [choiceFormId] :: Choice lbl a -> FormId -- | label [choiceLabel] :: Choice lbl a -> lbl -- | is the choice selected [choiceIsSelected] :: Choice lbl a -> Bool -- | the haskell value of the choice [choiceVal] :: Choice lbl a -> a -- | used for constructing elements like <input -- type="text">, which pure a single input value. input :: (Environment m input, FormError input err) => (input -> Either err a) -> (FormId -> a -> view) -> a -> Form m input err view a -- | used for elements like <input type="submit"> which are -- not always present in the form submission data. inputMaybe :: (Environment m input, FormError input err) => (input -> Either err a) -> (FormId -> Maybe a -> view) -> Maybe a -> Form m input err view (Maybe a) -- | used for elements like <input type="reset"> which take -- a value, but are never present in the form data set. inputNoData :: Environment m input => (FormId -> view) -> Form m input err view () -- | used for <input type="file"> inputFile :: forall m input err view ft. (Environment m input, FormInput input, FormError input err, ft ~ FileType input, Monoid ft) => (FormId -> view) -> Form m input err view (FileType input) -- | used for groups of checkboxes, <select -- multiple="multiple"> boxes inputMulti :: forall m input err view a lbl. (FormError input err, FormInput input, Environment m input, Eq a) => [(a, lbl)] -> (input -> Either err [a]) -> (FormId -> [Choice lbl a] -> view) -> (a -> Bool) -> Form m input err view [a] -- | radio buttons, single <select> boxes inputChoice :: forall a m err input lbl view. (FormError input err, FormInput input, Environment m input, Eq a, Monoid view) => (a -> Bool) -> NonEmpty (a, lbl) -> (input -> Either err a) -> (FormId -> [Choice lbl a] -> view) -> Form m input err view a -- | this is necessary in order to basically map over the decoding function inputList :: forall m input err a view. (Monad m, FormError input err, Environment m input) => (input -> m (Either err [a])) -> ([view] -> view) -> [a] -> view -> (a -> Form m input err view a) -> Form m input err view [a] -- | used to create <label> elements label :: Environment m input => (FormId -> view) -> Form m input err view () -- | used to add a list of err messages to a Form -- -- This function automatically takes care of extracting only the errors -- that are relevent to the form element it is attached to via -- <* or *>. errors :: Environment m input => ([err] -> view) -> Form m input err view () -- | similar to errors but includes err messages from children of -- the form as well. childErrors :: Environment m input => ([err] -> view) -> Form m input err view () -- | modify the view of a form based on its errors withErrors :: Environment m input => (view -> [err] -> view) -> Form m input err view a -> Form m input err view a -- | modify the view of a form based on its child errors withChildErrors :: Monad m => (view -> [err] -> view) -> Form m input err view a -> Form m input err view a -- | This module provides helper functions for HTML input elements. These -- helper functions are not specific to any particular web framework or -- html library. -- -- For unnamed (enumerated) formlets, see -- Ditto.Generalized.Unnamed module Ditto.Generalized.Named -- | a choice for inputChoice data Choice lbl a Choice :: FormId -> lbl -> Bool -> a -> Choice lbl a -- | the formId [choiceFormId] :: Choice lbl a -> FormId -- | label [choiceLabel] :: Choice lbl a -> lbl -- | is the choice selected [choiceIsSelected] :: Choice lbl a -> Bool -- | the haskell value of the choice [choiceVal] :: Choice lbl a -> a -- | used for constructing elements like <input -- type="text">, which pure a single input value. input :: (Environment m input, FormError input err) => Text -> (input -> Either err a) -> (FormId -> a -> view) -> a -> Form m input err view a -- | used for elements like <input type="submit"> which are -- not always present in the form submission data. inputMaybe :: (Environment m input, FormError input err) => Text -> (input -> Either err a) -> (FormId -> Maybe a -> view) -> Maybe a -> Form m input err view (Maybe a) -- | used for elements like <input type="reset"> which take -- a value, but are never present in the form data set. inputNoData :: Environment m input => Text -> (FormId -> view) -> Form m input err view () -- | used for <input type="file"> inputFile :: forall m input err view ft. (Environment m input, FormInput input, FormError input err, ft ~ FileType input, Monoid ft) => Text -> (FormId -> view) -> Form m input err view (FileType input) -- | used for groups of checkboxes, <select -- multiple="multiple"> boxes inputMulti :: forall m input err view a lbl. (FormError input err, FormInput input, Environment m input, Eq a) => Text -> [(a, lbl)] -> (input -> Either err [a]) -> (FormId -> [Choice lbl a] -> view) -> (a -> Bool) -> Form m input err view [a] -- | radio buttons, single <select> boxes inputChoice :: forall a m err input lbl view. (FormError input err, FormInput input, Environment m input, Eq a, Monoid view) => Text -> (a -> Bool) -> NonEmpty (a, lbl) -> (input -> Either err a) -> (FormId -> [Choice lbl a] -> view) -> Form m input err view a -- | this is necessary in order to basically map over the decoding function inputList :: forall m input err a view. (Monad m, FormError input err, Environment m input) => Text -> (input -> m (Either err [a])) -> ([view] -> view) -> [a] -> view -> (a -> Form m input err view a) -> Form m input err view [a] -- | used to create <label> elements label :: Environment m input => Text -> (FormId -> view) -> Form m input err view () -- | used to add a list of err messages to a Form -- -- This function automatically takes care of extracting only the errors -- that are relevent to the form element it is attached to via -- <* or *>. errors :: Environment m input => ([err] -> view) -> Form m input err view () -- | similar to errors but includes err messages from children of -- the form as well. childErrors :: Environment m input => ([err] -> view) -> Form m input err view () -- | modify the view of a form based on its errors withErrors :: Environment m input => (view -> [err] -> view) -> Form m input err view a -> Form m input err view a -- | modify the view of a form based on its child errors withChildErrors :: Monad m => (view -> [err] -> view) -> Form m input err view a -> Form m input err view a -- | a Form with no view ireq :: forall m input view err a. (Monoid view, Environment m input, FormError input err) => Text -> (input -> Either err a) -> a -> Form m input err view a -- | an optional Form with no view iopt :: forall m input view err a. (Monoid view, Environment m input, FormError input err) => Text -> (input -> Either err a) -> Maybe a -> Form m input err view (Maybe a) -- | Reexports important modules of ditto module Ditto