Skip to content

Instantly share code, notes, and snippets.

@spion
Last active November 9, 2015 22:32
Show Gist options
  • Save spion/21aec146228fd008999e to your computer and use it in GitHub Desktop.
Save spion/21aec146228fd008999e to your computer and use it in GitHub Desktop.
module ValidEmail (mkEmail, emailToString, EmailAddress) where
newtype EmailAddress = ValidAddress String
validate :: String -> Boolean
validate email = ...
mkEmail :: String -> Maybe ValidEmail
mkEmail = case validate email of
True -> Just $ ValidAddress email
False -> Nothing
emailToString :: EmailAddress -> String
emailToString (ValidAddress email) = email
-- Note: ValidAddress is not exported, so its impossible
-- to make a valid email without using mkEmail
module MyFunctions (sendMsg)_ where
import ValidEmail (EmailAddress)
-- this function can now specify its demands
sendMsg :: EmailAddress -> IO ()
sendMsg = ... -- no validation required. We can use emailToString if we need
-- to convert the address to form the email headers
module OtherModule where
import MyFunctions (sendMsg)
main = do
email <- getLine
-- I dont need to remember that sendMsg demands a valid email, the compiler will tell me.
-- I don't have to remember it anywhere I use this function. If I use this function at least 2 times,
-- writing the type already paid off, after that, everything is a gain.
-- This is a type error
sendMsg email
module OtherModule where
import MyFunctions (sendMsg)
import ValidEmail (mkEmail)
main :: IO ()
main = do
unknownString <- getLine
maybeEmail <- mkEmail unknownString
-- I only need to check this once. after that, all functions that use the EmailAddress
-- type can pass it around freely without any checks whatsoever.
-- Furthermore, I don't have to keep track if I'm inside the "checked" subset of functions or I am not
-- The compiler keeps track of that for me - if it takes a String, i don't need to pre-check. If it
-- takes an EmailAddress, I must hand off a valid one either by making one from a string, or passing
-- a valid one.
case maybeEmail of
Just emailAddr -> sendMsg emailAddr
-- warning if we don't handle other case
Nothing -> putStrLn "Invalid email"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment