git.iko.soy/typeable/validationt
on master help sign in
Merge pull request #8 from ilyakooo0/added-readme
c2b7f2bDenis Redozubov
README.mdnew file+75
@@ -0,0 +1,75 @@
1+![Travis CI Badge](https://img.shields.io/travis/typeable/validationt)
2+
3+# ValidationT
4+
5+A very small validation data library.
6+
7+## Usage
8+
9+Suppose you want to validate some data from the user. Say, that the password adheres to some rules.
10+
11+You might do something like this:
12+
13+```haskell
14+validatePassword :: Monad m => String -> ValidationT [String] m ()
15+validatePassword password = do
16+ vLength password
17+ vAlpha password
18+ vNum password
19+ where
20+ vLength p = when (length p < 8)
21+ $ vWarning ["The password should be at least 8 characters long."]
22+ vAlpha p = unless (any isAlpha p)
23+ $ vWarning ["The password should contain at least one alphabetic character."]
24+ vNum p = unless (any isDigit p)
25+ $ vWarning ["The password should contain at least one numeric character."]
26+```
27+
28+`ValidationT e m a` essentially just gathers the errors thrown by `vWarning`.
29+
30+```haskell
31+vWarning :: (Monad m, Monoid e) => e -> ValidationT e m ()
32+```
33+
34+`vWarning` `mappend`s the given `e` to the already collected errors. This is why the warnings are contained inside a list.
35+
36+There is also `vError`. The only difference between `vWarning` and `vError` is that `vError` stops further execution (and further collection of errors and warnings).
37+
38+You would use the validation like this:
39+
40+```haskell
41+main :: IO ()
42+main = do
43+ password <- getLine
44+ result <- runValidationTEither . validatePassword $ password
45+ putStrLn $ case result of
46+ Left errs -> unlines err
47+ Right () -> "You are fine."
48+```
49+
50+You 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.
51+
52+The 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:
53+
54+```haskell
55+data Piece
56+ = Password
57+ | UserName
58+ deriving (Eq, Show, Ord)
59+
60+validatePassword :: Monad m => String -> ValidationT (MonoidMap Piece [String]) m ()
61+validatePassword password = do
62+ vLength password
63+ vAlpha password
64+ vNum password
65+ where
66+ warning = mmSingleton UserName
67+ vLength p = when (length p < 8)
68+ $ warning ["The password should be at least 8 characters long."]
69+ vAlpha p = unless (any isAlpha p)
70+ $ warning ["The password should contain at least one alphabetic character."]
71+ vNum p = unless (any isDigit p)
72+ $ warning ["The password should contain at least one numeric character."]
73+```
74+
75+(`mmSingleton` is a covenience initializer for `MonoidMap`.)