Skip to content

Instantly share code, notes, and snippets.

@davenportw15
Created January 9, 2016 20:25
Show Gist options
  • Save davenportw15/00f6aa0282e7ea47ae30 to your computer and use it in GitHub Desktop.
Save davenportw15/00f6aa0282e7ea47ae30 to your computer and use it in GitHub Desktop.
An implementation of the Either monad in Haskell
module Either where
import Prelude hiding (Either, Left, Right)
data Either failure success = Left failure | Right success
deriving (Show, Read, Eq)
instance Functor (Either failure) where
fmap _ (Left x) = Left x
fmap f (Right x) = Right (f x)
instance Applicative (Either failure) where
pure = Right
Right f <*> Right x = Right (f x)
_ <*> Left x = Left x
instance Monad (Either failure) where
return = Right
Right x >>= f = f x
Left x >>= _ = Left x
-- Example usage: validating posts
data Post = Post
{ userID :: Int
, title :: String
, contents :: String
} deriving (Show, Read, Eq)
hasTitle :: Post -> Either String Post
hasTitle post
| null (title post) = Left "post must have a title"
| otherwise = Right post
hasContents :: Post -> Either String Post
hasContents post
| length (contents post) <= 160 = Right post
| otherwise = Left "post must be less than 160 characters"
validatePost :: Post -> Either String Post
validatePost post = hasTitle post >>= hasContents
main :: IO ()
main = do
let posts = [ Post 1 "First post!" "Hi everyone, this is my first post!"
, Post 2 "" "Whoops, I forgot a title"
, Post 3 "Here's a title" "A really, really, really, really, really, really, really, really, really, really, really, really, really, really, really, really, really, really, really, really, really, really, really, really, long post."
]
mapM_ (print . validatePost) posts
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment