Skip to content

Instantly share code, notes, and snippets.

@wbadart
Created January 1, 2021 00:44
Show Gist options
  • Save wbadart/81d755ac8ad0e0db5a3e3bd13bc8c7fe to your computer and use it in GitHub Desktop.
Save wbadart/81d755ac8ad0e0db5a3e3bd13bc8c7fe to your computer and use it in GitHub Desktop.
{-# LANGUAGE LambdaCase #-}
module Lib where
import Data.Char
import Data.List.NonEmpty ( NonEmpty )
import Validation
data PasswordError
= TooShort
| TooLong
| MissingLowercase
| MissingUppercase
| MissingDigit
| MissingSymbol
| HasSpace
deriving Show
newtype Password = Password { unPassword :: String } deriving Show
validatePassword :: String -> Validation (NonEmpty PasswordError) Password
validatePassword s = Password s
<$ failureIf (length s < 8) TooShort
<* failureIf (length s > 64) TooLong
<* failureUnless (any isLower s) MissingLowercase
<* failureUnless (any isUpper s) MissingUppercase
<* failureUnless (any isDigit s) MissingDigit
<* failureUnless (any isSymbol' s) MissingSymbol
<* failureIf (any isSpace s) HasSpace
where isSymbol' = (||) <$> isSymbol <*> isPunctuation
data EmailError
= InvalidError
deriving Show
newtype Email = Email { unEmail :: String } deriving Show
validateEmail :: String -> Validation (NonEmpty EmailError) Email
validateEmail s = Email s
<$ failureUnless (elem '@' s) InvalidError
data UserError
= PasswordError PasswordError
| EmailError EmailError
deriving Show
data User = User
{ userEmail :: Email
, userPassword :: Password
} deriving Show
parseUser :: String -> String -> Validation (NonEmpty UserError) User
parseUser email password = User
<$> mapFailure (fmap EmailError) (validateEmail email)
<*> mapFailure (fmap PasswordError) (validatePassword password)
mapFailure :: (e -> e') -> Validation e a -> Validation e' a
mapFailure f = \case
Failure e -> Failure (f e)
Success a -> Success a
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment