-- 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.3
-- | Module for the core result type, and related functions
module Ditto.Result
-- | Type for failing computations
data Result e ok
Error :: [(FormRange, e)] -> Result e ok
Ok :: ok -> Result e ok
-- | convert a Result to Maybe discarding the error message
-- on Error
getResult :: Result e ok -> Maybe ok
-- | An ID used to identify forms
data FormId
FormId :: String -> NonEmpty Int -> FormId
FormIdCustom :: String -> Int -> FormId
-- | The zero ID, i.e. the first ID that is usable
zeroId :: String -> FormId
-- | map a function over the NonEmpty Int inside a FormId
mapId :: (NonEmpty Int -> NonEmpty Int) -> FormId -> FormId
-- | A range of ID's to specify a group of forms
data FormRange
FormRange :: FormId -> FormId -> FormRange
-- | Increment a form ID
incrementFormId :: FormId -> FormId
-- | create a FormRange from a FormId
unitRange :: FormId -> FormRange
-- | Check if a FormId is contained in a FormRange
isInRange :: FormId -> FormRange -> Bool
-- | Check if a FormRange is contained in another FormRange
isSubRange :: FormRange -> FormRange -> Bool
-- | Select the errors for a certain range
retainErrors :: FormRange -> [(FormRange, e)] -> [e]
-- | Select the errors originating from this form or from any of the
-- children of this form
retainChildErrors :: FormRange -> [(FormRange, e)] -> [e]
instance GHC.Base.Functor (Ditto.Result.Result e)
instance (GHC.Classes.Eq e, GHC.Classes.Eq ok) => GHC.Classes.Eq (Ditto.Result.Result e ok)
instance (GHC.Show.Show e, GHC.Show.Show ok) => GHC.Show.Show (Ditto.Result.Result e ok)
instance GHC.Show.Show Ditto.Result.FormRange
instance GHC.Classes.Eq Ditto.Result.FormRange
instance GHC.Classes.Ord Ditto.Result.FormId
instance GHC.Classes.Eq Ditto.Result.FormId
instance GHC.Base.Monad (Ditto.Result.Result e)
instance GHC.Base.Applicative (Ditto.Result.Result e)
instance GHC.Show.Show Ditto.Result.FormId
-- | This module defines the Form type, its instances, core
-- manipulation functions, and a bunch of helper utilities.
module Ditto.Core
-- | 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
-- | Utility Function: trivially prove nothing about ()
unitProved :: FormId -> Proved ()
-- | inner state used by Form.
type FormState m input = ReaderT (Environment m input) (StateT FormRange m)
-- | 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
-- | Utility function: Get the current input
getFormInput :: Monad m => FormState m input (Value input)
-- | Utility function: Gets the input of an arbitrary FormId.
getFormInput' :: Monad m => FormId -> FormState m input (Value input)
-- | Utility function: Get the current range
getFormRange :: Monad m => FormState m i FormRange
-- | The environment is where you get the actual input per form.
--
-- The NoEnvironment constructor is typically used when generating
-- a view for a GET request, where no data has yet been submitted. This
-- will cause the input elements to use their supplied default values.
--
-- Note that NoEnviroment is different than supplying an empty
-- environment.
data Environment m input
Environment :: (FormId -> m (Value input)) -> Environment m input
NoEnvironment :: Environment m input
-- | Utility function: returns the current FormId. This will only
-- make sense if the form is not composed
getFormId :: Monad m => FormState m i FormId
getNamedFormId :: Monad m => String -> FormState m i FormId
-- | Utility function: increment the current FormId.
incFormId :: Monad m => FormState m i ()
-- | A view represents a visual representation of a form. It is composed of
-- a function which takes a list of all errors and then produces a new
-- view
newtype View err v
View :: ([(FormRange, err)] -> v) -> View err v
[unView] :: View err v -> [(FormRange, err)] -> v
-- | a Form contains a View combined with a validation
-- function which will attempt to extract a value from submitted form
-- data.
--
-- It is highly parameterized, allowing it work in a wide variety of
-- different configurations. You will likely want to make a type alias
-- that is specific to your application to make type signatures more
-- manageable.
--
--
-- - m A monad which can be used by the validator
-- - input A framework specific type for representing
-- the raw key/value pairs from the form data
-- - err A application specific type for err
-- messages
-- - view The type of data being generated for the view
-- (HSP, Blaze Html, Heist, etc)
-- - proof A type which names what has been proved
-- about the pure value. () means nothing has been proved.
-- - a Value pure by form when it is successfully
-- decoded, validated, etc.
--
--
-- This type is very similar to the Form type from
-- digestive-functors <= 0.2. If proof is
-- (), then Form is an applicative functor and can be
-- used almost exactly like digestive-functors <= 0.2.
newtype Form m input err view a
Form :: FormState m input (View err view, m (Result err (Proved a))) -> Form m input err view a
[unForm] :: Form m input err view a -> FormState m input (View err view, m (Result err (Proved a)))
bracketState :: Monad m => FormState m input a -> FormState m input a
-- | This provides a Monad instance which will stop rendering on err. This
-- instance isn't a part of Form because of its undesirable
-- behavior. -XApplicativeDo is generally preferred
newtype MForm m input err view a
MForm :: Form m input err view a -> MForm m input err view a
[runMForm] :: MForm m input err view a -> Form m input err view a
runAsMForm :: Monad m => Environment m input -> Text -> Form m input err view a -> m (View err view, m (Result err (Proved a)))
-- | Run a form
runForm :: Monad m => Environment m input -> Text -> Form m input err view a -> m (View err view, m (Result err (Proved a)))
-- | Run a form
runForm' :: Monad m => Environment m input -> Text -> Form m input err view a -> m (view, Maybe a)
-- | Just evaluate the form to a view. This usually maps to a GET request
-- in the browser.
viewForm :: Monad m => Text -> Form m input err view a -> m view
-- | 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 => Environment m input -> Text -> Form m input err view a -> m (Either view a)
-- | create a Form from some view.
--
-- This is typically used to turn markup like <br> into a
-- Form.
view :: Monad m => view -> Form m input err view ()
-- | Append a unit form to the left. This is useful for adding labels or
-- err fields.
--
-- The Forms on the left and right hand side will share the same
-- FormId. This is useful for elements like <label
-- for="someid">, which need to refer to the id of another
-- element.
(++>) :: (Monad m, Semigroup view) => Form m input err view z -> Form m input err view a -> Form m input err view a
infixl 6 ++>
-- | Append a unit form to the right. See ++>.
(<++) :: (Monad m, Semigroup view) => Form m input err view a -> Form m input err view z -> Form m input err view a
infixr 5 <++
-- | 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
-- | infix mapView: succinct `foo @$ do ..`
(@$) :: Monad m => (view -> view) -> Form m input err view a -> Form m input err view a
infixr 0 @$
-- | Utility Function: turn a view and pure value into a successful
-- FormState
mkOk :: Monad m => FormId -> view -> a -> FormState m input (View err view, m (Result err (Proved a)))
instance (GHC.Base.Monoid view, GHC.Base.Monad m) => GHC.Base.Applicative (Ditto.Core.MForm m input err view)
instance (GHC.Base.Monad m, GHC.Base.Monoid view) => GHC.Base.Alternative (Ditto.Core.MForm m input err view)
instance GHC.Base.Functor m => Data.Bifunctor.Bifunctor (Ditto.Core.MForm m input err)
instance GHC.Base.Functor m => GHC.Base.Functor (Ditto.Core.MForm m input err view)
instance GHC.Base.Functor m => GHC.Base.Functor (Ditto.Core.Form m input err view)
instance GHC.Base.Functor (Ditto.Core.View err)
instance GHC.Base.Monoid v => GHC.Base.Monoid (Ditto.Core.View err v)
instance GHC.Base.Semigroup v => GHC.Base.Semigroup (Ditto.Core.View err v)
instance GHC.Base.Functor Ditto.Core.Proved
instance GHC.Show.Show a => GHC.Show.Show (Ditto.Core.Proved a)
instance (GHC.Base.Monad m, GHC.Base.Monoid view) => GHC.Base.Monad (Ditto.Core.MForm m input err view)
instance (GHC.Base.Functor m, GHC.Base.Monoid view, GHC.Base.Monad m) => GHC.Base.Applicative (Ditto.Core.Form m input err view)
instance (GHC.Base.Monad m, GHC.Base.Monoid view) => GHC.Base.Alternative (Ditto.Core.Form m input err view)
instance GHC.Base.Functor m => Data.Bifunctor.Bifunctor (Ditto.Core.Form m input err)
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.Monoid view, GHC.Base.Monad m, GHC.Base.Semigroup a) => GHC.Base.Monoid (Ditto.Core.Form m input err view a)
instance (GHC.Base.Semigroup input, GHC.Base.Monad m) => GHC.Base.Semigroup (Ditto.Core.Environment m input)
instance (GHC.Base.Semigroup input, GHC.Base.Monad m) => GHC.Base.Monoid (Ditto.Core.Environment m input)
-- | 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:
newtype Proof m error a b
Proof :: (a -> m (Either error b)) -> Proof m error a b
-- | function which provides the proof
[proofFunction] :: Proof m error a b -> a -> m (Either error b)
-- | apply a Proof to a Form
prove :: Monad m => Form m input error view a -> Proof m error a b -> Form m input error view b
-- | transform a Form using a Proof, and the replace the
-- proof with ().
--
-- This is useful when you want just want classic digestive-functors
-- behaviour.
transform :: Monad m => 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 => Form m input error view a -> (a -> m (Either error b)) -> Form m input error view b
-- | transform the Form result using an Either function.
transformEither :: Monad m => Form m input error view a -> (a -> Either error 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) -> Proof m error String i
-- | read signed decimal number
signedDecimal :: (Monad m, Eq i, Real i) => (String -> error) -> Proof m error String i
-- | read RealFrac number
realFrac :: (Monad m, RealFrac a) => (String -> error) -> Proof m error String a
-- | read a signed RealFrac number
realFracSigned :: (Monad m, RealFrac a) => (String -> error) -> Proof m error String a
-- | 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 err input | err -> input
commonFormError :: FormError err input => 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 error input) => input -> Either error String
-- | Should be implemented
getInputStrings :: FormInput input => input -> [String]
-- | Parse the input value into Text
getInputText :: (FormInput input, FormError error input) => input -> Either error Text
-- | Can be overriden for efficiency concerns
getInputTexts :: FormInput input => input -> [Text]
-- | Get a file descriptor for an uploaded file
getInputFile :: (FormInput input, FormError error input) => input -> Either error (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
module Ditto.Generalized.Named
-- | used for constructing elements like <input
-- type="text">, which pure a single input value.
input :: (Monad m, FormError err input) => String -> (input -> Either err a) -> (FormId -> a -> view) -> a -> Form m input err view a
-- | used to construct elements with optional initial values, which are
-- still required
inputMaybeReq :: (Monad m, FormError err input) => String -> (input -> Either err a) -> (FormId -> Maybe a -> view) -> Maybe 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 :: (Monad m, FormError err input) => String -> (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 :: Monad m => String -> (FormId -> view) -> Form m input err view ()
-- | used for <input type="file">
inputFile :: forall m input err view. (Monad m, FormInput input, FormError err input) => String -> (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 err input, FormInput input, Monad m) => String -> [(a, lbl)] -> (FormId -> [(FormId, Int, lbl, Bool)] -> view) -> (a -> Bool) -> Form m input err view [a]
-- | radio buttons, single <select> boxes
inputChoice :: forall a m err input lbl view. (FormError err input, FormInput input, Monad m) => String -> (a -> Bool) -> [(a, lbl)] -> (FormId -> [(FormId, Int, lbl, Bool)] -> view) -> Form m input err view a
-- | radio buttons, single <select> boxes
inputChoiceForms :: forall a m err input lbl view. (Monad m, FormError err input, FormInput input) => String -> a -> [(Form m input err view a, lbl)] -> (FormId -> [(FormId, Int, FormId, view, lbl, Bool)] -> view) -> Form m input err view a
-- | used to create <label> elements
label :: Monad m => String -> (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 :: Monad m => ([err] -> view) -> Form m input err view ()
-- | similar to errors but includes err messages from children of
-- the form as well.
childErrors :: Monad m => ([err] -> view) -> Form m input err view ()
-- | modify the view of a form based on its errors
withErrors :: Monad m => (view -> [err] -> view) -> Form m input err view a -> Form m input err view a
module Ditto.Generalized
-- | used for constructing elements like <input
-- type="text">, which pure a single input value.
input :: (Monad m, FormError err input) => (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 :: (Monad m, FormError err input) => (input -> Either err a) -> (FormId -> Maybe a -> view) -> Maybe a -> Form m input err view (Maybe a)
-- | used to construct elements with optional initial values, which are
-- still required
inputMaybeReq :: (Monad m, FormError err input) => (input -> Either err a) -> (FormId -> Maybe a -> view) -> Maybe a -> Form m input err view a
-- | used for elements like <input type="reset"> which take
-- a value, but are never present in the form data set.
inputNoData :: Monad m => (FormId -> view) -> Form m input err view ()
-- | used for <input type="file">
inputFile :: forall m input err view. (Monad m, FormInput input, FormError err input) => (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 err input, FormInput input, Monad m) => [(a, lbl)] -> (FormId -> [(FormId, Int, lbl, Bool)] -> view) -> (a -> Bool) -> Form m input err view [a]
-- | radio buttons, single <select> boxes
inputChoice :: forall a m err input lbl view. (FormError err input, FormInput input, Monad m) => (a -> Bool) -> [(a, lbl)] -> (FormId -> [(FormId, Int, lbl, Bool)] -> view) -> Form m input err view a
-- | radio buttons, single <select> boxes
inputChoiceForms :: forall a m err input lbl view. (Monad m, FormError err input, FormInput input) => a -> [(Form m input err view a, lbl)] -> (FormId -> [(FormId, Int, FormId, view, lbl, Bool)] -> view) -> Form m input err view a
-- | used to create <label> elements
label :: Monad m => (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 :: Monad m => ([err] -> view) -> Form m input err view ()
-- | similar to errors but includes err messages from children of
-- the form as well.
childErrors :: Monad m => ([err] -> view) -> Form m input err view ()
-- | modify the view of a form based on its errors
withErrors :: Monad m => (view -> [err] -> view) -> Form m input err view a -> Form m input err view a
module Ditto