Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@gustavofranke
Created February 3, 2020 23:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gustavofranke/cd577473c5538c997b4c32427c128bea to your computer and use it in GitHub Desktop.
Save gustavofranke/cd577473c5538c997b4c32427c128bea to your computer and use it in GitHub Desktop.
-- from
-- https://www.youtube.com/watch?v=lxjIUWGMUqE
-- Haskell at Work - Validation with Smart Constructors
module SerialNumber
( SerialNumber
, ValidataionError(..)
, makeSerialNumber
, renderSerialNumber
) where
import Data.Text (Text)
import qualified Data.Text as Text
import qualified Data.HashSet as HashSet
import Data.HashSet (HashSet)
newtype SerialNumber =
SerialNumber [Text]
deriving (Eq, Show)
data ValidataionError
= WrongNumerOfGroups Int
| InvalidGroupLength Int
Text
| InvalidCharacters (HashSet Char)
deriving (Eq, Show)
validChars = HashSet.fromList (['A' .. 'Z'] ++ ['0' .. '9'])
separator :: Text
separator = Text.singleton '-'
makeSerialNumber :: Text -> Either ValidataionError SerialNumber
makeSerialNumber t = do
gs <- mapM validateGroup (Text.splitOn (Text.singleton '-') t)
if length gs == 4
then Right (SerialNumber gs)
else Left (WrongNumerOfGroups (length gs))
where
validateGroup group
| len /= 4 = Left(InvalidGroupLength len group)
| not (HashSet.null invalidChars) = Left (InvalidCharacters invalidChars)
| otherwise = Right group
where
len = Text.length group
invalidChars = HashSet.difference (HashSet.fromList (Text.unpack group)) validChars
renderSerialNumber :: SerialNumber -> Text
renderSerialNumber (SerialNumber groups) =
Text.intercalate separator groups
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment