-- 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:
--
--
-- - Left view on failure. The view will have
-- already been applied to the errors.
-- - Right a on success.
--
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:
--
--
-- - verifies that the input value meets some criteria
-- - optionally transforms the input value to another value while
-- preserving that criteria
-- - puts the proof name in type-signature where the type-checker can
-- use it
--
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