https://github.com/typeable/validationt
Straightforward validation monad. Convenient for validating web forms and APIs.
https://github.com/typeable/validationt
web
Last synced: 10 months ago
JSON representation
Straightforward validation monad. Convenient for validating web forms and APIs.
- Host: GitHub
- URL: https://github.com/typeable/validationt
- Owner: typeable
- License: bsd-3-clause
- Created: 2017-05-17T10:06:19.000Z (over 8 years ago)
- Default Branch: master
- Last Pushed: 2024-01-08T09:32:46.000Z (about 2 years ago)
- Last Synced: 2024-04-25T01:08:22.143Z (almost 2 years ago)
- Topics: web
- Language: Haskell
- Size: 33.2 KB
- Stars: 5
- Watchers: 16
- Forks: 3
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Changelog: ChangeLog.md
- License: LICENSE
Awesome Lists containing this project
README

# ValidationT
A simple data validation library. The main idea is to provide an easy way to
validate web form data by aggregating errors for each field.
## Usage
Suppose you want to validate some data from the user. Say, that the password adheres to some rules.
You might do something like this:
```haskell
validatePassword :: Monad m => String -> ValidationT [String] m ()
validatePassword password = do
vLength password
vAlpha password
vNum password
where
vLength p = when (length p < 8)
$ vWarning ["The password should be at least 8 characters long."]
vAlpha p = unless (any isAlpha p)
$ vWarning ["The password should contain at least one alphabetic character."]
vNum p = unless (any isDigit p)
$ vWarning ["The password should contain at least one numeric character."]
```
`ValidationT e m a` essentially just gathers the errors thrown by `vWarning`.
```haskell
vWarning :: (Monad m, Monoid e) => e -> ValidationT e m ()
```
`vWarning` `mappend`s the given `e` to the already collected errors. This is why the warnings are contained inside a list.
There is also `vError`. The only difference between `vWarning` and `vError` is that `vError` stops further execution (and further collection of errors and warnings).
You would use the validation like this:
```haskell
main :: IO ()
main = do
password <- getLine
result <- runValidationTEither . validatePassword $ password
putStrLn $ case result of
Left errs -> unlines err
Right () -> "You are fine."
```
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.
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:
```haskell
data Piece
= Password
| UserName
deriving (Eq, Show, Ord)
validatePassword :: Monad m => String -> ValidationT (MonoidMap Piece [String]) m ()
validatePassword password = do
vLength password
vAlpha password
vNum password
where
warning = mmSingleton UserName
vLength p = when (length p < 8)
$ warning ["The password should be at least 8 characters long."]
vAlpha p = unless (any isAlpha p)
$ warning ["The password should contain at least one alphabetic character."]
vNum p = unless (any isDigit p)
$ warning ["The password should contain at least one numeric character."]
```
(`mmSingleton` is a covenience initializer for `MonoidMap`.)