git.iko.soy/typeable/validationt
on 0.3.0 help sign in
76 lines 2.7 kB history raw
1![Travis CI Badge](https://img.shields.io/travis/typeable/validationt)
3# ValidationT
5A simple data validation library. The main idea is to provide an easy way to
6validate web form data by aggregating errors for each field.
8## Usage
10Suppose you want to validate some data from the user. Say, that the password adheres to some rules.
12You might do something like this:
14```haskell
15validatePassword :: Monad m => String -> ValidationT [String] m ()
16validatePassword password = do
17 vLength password
18 vAlpha password
19 vNum password
20 where
21 vLength p = when (length p < 8)
22 $ vWarning ["The password should be at least 8 characters long."]
23 vAlpha p = unless (any isAlpha p)
24 $ vWarning ["The password should contain at least one alphabetic character."]
25 vNum p = unless (any isDigit p)
26 $ vWarning ["The password should contain at least one numeric character."]
27```
29`ValidationT e m a` essentially just gathers the errors thrown by `vWarning`.
31```haskell
32vWarning :: (Monad m, Monoid e) => e -> ValidationT e m ()
33```
35`vWarning` `mappend`s the given `e` to the already collected errors. This is why the warnings are contained inside a list.
37There is also `vError`. The only difference between `vWarning` and `vError` is that `vError` stops further execution (and further collection of errors and warnings).
39You would use the validation like this:
41```haskell
42main :: IO ()
43main = do
44 password <- getLine
45 result <- runValidationTEither . validatePassword $ password
46 putStrLn $ case result of
47 Left errs -> unlines err
48 Right () -> "You are fine."
49```
51You could, of course, do more complicated things like use `vWarningL` and `vErrorL` to add an error to a `mempty` structure, which gets `mappend`ed with other errors.
53The library comes with a `MonoidMap` `newtype` wrapper around `Map`, which `mappend`s the values themselves on conflict. This can be useful if you have a multiple points of failure and you want to distinguich between them -- validating a username and a password for example:
55```haskell
56data Piece
57 = Password
58 | UserName
59 deriving (Eq, Show, Ord)
61validatePassword :: Monad m => String -> ValidationT (MonoidMap Piece [String]) m ()
62validatePassword password = do
63 vLength password
64 vAlpha password
65 vNum password
66 where
67 warning = mmSingleton UserName
68 vLength p = when (length p < 8)
69 $ warning ["The password should be at least 8 characters long."]
70 vAlpha p = unless (any isAlpha p)
71 $ warning ["The password should contain at least one alphabetic character."]
72 vNum p = unless (any isDigit p)
73 $ warning ["The password should contain at least one numeric character."]
74```
76(`mmSingleton` is a covenience initializer for `MonoidMap`.)