Created
January 9, 2016 20:25
-
-
Save davenportw15/00f6aa0282e7ea47ae30 to your computer and use it in GitHub Desktop.
An implementation of the Either monad in Haskell
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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