Skip to content

Instantly share code, notes, and snippets.

@naoto-ogawa
Created May 15, 2014 12: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 naoto-ogawa/e39989551799c124a2a2 to your computer and use it in GitHub Desktop.
Save naoto-ogawa/e39989551799c124a2a2 to your computer and use it in GitHub Desktop.
Exception Monado
--
-- Excerpt from Monads for functional programming
-- http://homepages.inf.ed.ac.uk/wadler/papers/marktoberdorf/baastad.pdf
--
-- 2.1 Variation zero: The basic evaluator
--
data Term = Con Int | Div Term Term
eval :: Term -> Int
eval (Con a) = a
eval (Div t v) = div (eval t) (eval v)
answer :: Term
answer = Div (Div (Con 1972) (Con 2)) (Con 23)
err :: Term
err = Div (Con 1) (Con 0)
-- 2.2 Variation one: Exceptions
--
data M a = Raise Exception | Return a deriving (Show)
type Exception = String
eval1 :: Term -> M Int
eval1 (Con a) = Return a
eval1 (Div t v) = case eval1 t of
Raise e -> Raise e
Return a -> case eval1 v of
Raise e -> Raise e
Return b -> if b==0
then Raise "divide by zero (eval1)"
else Return (div a b)
-- 2.7 Variation one, revisited: Exceptions
--
unit :: a -> M a
unit a = Return a
bind :: M a -> (a -> M b) -> M b
bind m k = case m of
Raise e -> Raise e
Return a -> k a
raise :: Exception -> M a
raise e = Raise e
eval2 :: Term -> M Int
eval2 (Con a) = unit a
eval2 (Div t v) = (eval2 t) `bind` λa -> eval2 v `bind` λb -> unit (div a b)
eval2' :: Term -> M Int
eval2' (Con a) = unit a
eval2' (Div t v) = (eval2' t) `bind` λa -> eval2' v `bind` λb -> if b == 0 then raise "divide by zero (eval2')" else unit (div a b)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment