Skip to content

Instantly share code, notes, and snippets.

@KirinDave
Last active May 29, 2018 18:05
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 KirinDave/7e8ed107c372e197e181ee716b34753e to your computer and use it in GitHub Desktop.
Save KirinDave/7e8ed107c372e197e181ee716b34753e to your computer and use it in GitHub Desktop.
{-# Language DeriveFunctor, FlexibleInstances #-}
module Lib where
newtype Mu f = Mu (f (Mu f))
data ArithF f =
ALit Int |
AAdd f f |
ASub f f deriving Functor
lit :: Int -> Arith
lit i = Mu $ ALit i
add :: Arith -> Arith -> Arith
add x y = Mu $ AAdd x y
sub :: Arith -> Arith -> Arith
sub x y = Mu $ ASub x y
cata :: Functor f => (f a -> a) -> Mu f -> a
cata f (Mu g) = f (fmap (cata f) g)
type Arith = Mu ArithF
type Alg f a = f a -> a
-- This is why we need FlexibleInstances
instance Show (Mu ArithF) where
show = cata printer
printer :: Alg ArithF String
printer (ALit i) = show i
printer (AAdd l r) = "(" ++ l ++ " + " ++ r ++ ")"
printer (ASub l r) = "(" ++ l ++ " - " ++ r ++ ")"
interpreter :: Alg ArithF Int
interpreter (ALit i) = i
interpreter (AAdd l r) = l + r
interpreter (ASub l r) = l - r
keep :: Alg ArithF Arith
keep = Mu
(<+>) :: Functor f => Alg f a -> Alg f b -> Alg f (a,b)
c1 <+> c2 = \f -> (c1 $ fmap fst f,
c2 $ fmap snd f)
eval :: Arith -> (Int, String)
eval = cata (interpreter <+> printer)
annotated :: Arith -> (Int, Arith)
annotated = cata (interpreter <+> keep)
full :: Arith -> (Int, (String, Arith))
full = cata (interpreter <+> (printer <+> keep))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment