bound-0.5: examples/Overkill.hs
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE ExistentialQuantification #-}
{-# LANGUAGE TypeOperators #-}
module Overkill where
import Data.Vector as Vector hiding ((++), map)
import Data.List as List
import Data.Foldable
import Data.Traversable
import Data.Monoid (Monoid(..))
import Control.Monad
import Control.Monad.Trans.Class
import Control.Applicative
import Prelude hiding (foldr)
import Prelude.Extras
import GHC.Prim (Constraint(..))
import Unsafe.Coerce
import Bound
infixl 9 :@
infixr 5 :>
-- little orphan instances
instance Show1 Vector where showsPrec1 = showsPrec
instance Eq1 Vector where (==#) = (==)
data Exp a
= Var a
| Exp a :@ Exp a
| forall (b :: Index). Lam (Pat b Exp a) (Scope (Path b) Exp a)
| Let (Vector (Scope Int Exp a)) (Scope Int Exp a)
data Index = VarI | WildI | AsI Index | ConI [Index]
data Pat :: Index -> (* -> *) -> * -> * where
VarP :: Pat VarI f a
WildP :: Pat WildI f a
AsP :: Pat i f a -> Pat (AsI i) f a
ConP :: String -> Pats bs f a -> Pat (ConI bs) f a
ViewP :: f a -> Pat b f a -> Pat b f a -- TODO: allow references to earlier variables
data Pats :: [Index] -> (* -> *) -> * -> * where
NilP :: Pats '[] f a
(:>) :: Pat b f a -> Pats bs f a -> Pats (b ': bs) f a
data Path :: Index -> * where
V :: Path VarI
L :: Path (AsI a)
R :: Path a -> Path (AsI a)
C :: MPath as -> Path (ConI as)
data MPath :: [Index] -> * where
H :: Path a -> MPath (a ':as)
T :: MPath as -> MPath (a ':as)
instance Functor Exp where
fmap = fmapDefault
instance Foldable Exp where
foldMap = foldMapDefault
instance Applicative Exp where
pure = Var
(<*>) = ap
instance Traversable Exp where
traverse f (Var a) = Var <$> f a
traverse f (x :@ y) = (:@) <$> traverse f x <*> traverse f y
traverse f (Lam p e) = Lam <$> traverse f p <*> traverse f e
traverse f (Let bs e) = Let <$> traverse (traverse f) bs <*> traverse f e
instance Monad Exp where
return = Var
Var a >>= f = f a
(x :@ y) >>= f = (x >>= f) :@ (y >>= f)
Lam p e >>= f = Lam (p >>>= f) (e >>>= f)
Let bs e >>= f = Let (fmap (>>>= f) bs) (e >>>= f)
instance Eq a => Eq (Exp a) where (==) = (==#)
instance Eq1 Exp where
Var a ==# Var b = a == b
(a :@ b) ==# (c :@ d) = a ==# c && b ==# d
Lam ps a ==# Lam qs b = eqPat ps qs && a ==# unsafeCoerce b -- eqPat proves equal shape
Let as a ==# Let bs b = as == bs && a ==# b
_ ==# _ = False
instance Show a => Show (Exp a) where showsPrec = showsPrec1
instance Show1 Exp where
showsPrec1 d (Var a) = showParen (d > 10) $ showString "Var " . showsPrec 11 a
showsPrec1 d (a :@ b) = showParen (d > 9) $ showsPrec1 9 a . showString " :@ " . showsPrec1 10 b
showsPrec1 d (Lam ps b) = showParen (d > 10) $ showString "Lam " . showsPrec1 11 ps . showChar ' ' . showsPrec1 11 b
showsPrec1 d (Let bs b) = showParen (d > 10) $ showString "Let " . showsPrec1 11 bs . showChar ' ' . showsPrec1 11 b
-- * smart lam
-- ** smart patterns
data P a = forall b. P (Pat b Exp a) [a] (a -> Maybe (Path b))
varp :: Eq a => a -> P a
varp a = P VarP [a] (\v -> if a == v then Just V else Nothing)
wildp :: P a
wildp = P WildP [] (const Nothing)
asp :: Eq a => a -> P a -> P a
asp a (P p as f) = P (AsP p) (a:as) $ \v -> case f v of
Just b -> Just (R b)
Nothing | a == v -> Just L
| otherwise -> Nothing
data Ps a = forall bs. Ps (Pats bs Exp a) [a] (a -> Maybe (MPath bs))
conp :: String -> [P a] -> P a
conp g ps = case go ps of
Ps qs as f -> P (ConP g qs) as (fmap C . f)
where
go :: [P a] -> Ps a
go [] = Ps NilP [] (const Nothing)
go (P p as f : xs) = case go xs of
Ps ps ass g -> Ps (p :> ps) (as ++ ass) $ \v ->
T <$> g v <|> H <$> f v
-- * smart lam
lam :: P a -> Exp a -> Exp a
lam (P p _ f) t = Lam p (abstract f t)
-- * smart let
let_ :: Eq a => [(a, Exp a)] -> Exp a -> Exp a
let_ bs b = Let (Vector.fromList $ map (abstr . snd) bs) (abstr b)
where vs = map fst bs
abstr = abstract (`List.elemIndex` vs)
-- * Pat
-- ** A Kind of Shape
eqPat :: (Eq1 f, Eq a) => Pat b f a -> Pat b' f a -> Bool
eqPat VarP VarP = True
eqPat WildP WildP = True
eqPat (AsP p) (AsP q) = eqPat p q
eqPat (ConP g ps) (ConP h qs) = g == h && eqPats ps qs
eqPat (ViewP e p) (ViewP f q) = e ==# f && eqPat p q
instance Eq1 f => Eq1 (Pat b f) where (==#) = eqPat
instance (Eq1 f, Eq a) => Eq (Pat b f a) where (==) = eqPat
instance Show1 f => Show1 (Pat b f) where showsPrec1 = showsPrec
instance (Show1 f, Show a) => Show (Pat b f a) where
showsPrec _ VarP = showString "VarP"
showsPrec _ WildP = showString "WildP"
showsPrec d (AsP p) = showParen (d > 10) $ showString "AsP " . showsPrec 11 p
showsPrec d (ConP g ps) = showParen (d > 10) $ showString "ConP " . showsPrec 11 g . showChar ' ' . showsPrec 11 ps
showsPrec d (ViewP e p) = showParen (d > 10) $ showString "ViewP " . showsPrec1 11 e . showChar ' ' . showsPrec 11 p
instance Functor f => Functor (Pat b f) where
fmap _ VarP = VarP
fmap _ WildP = WildP
fmap f (AsP p) = AsP (fmap f p)
fmap f (ConP g ps) = ConP g (fmap f ps)
fmap f (ViewP e p) = ViewP (fmap f e) (fmap f p)
instance Foldable f => Foldable (Pat b f) where
foldMap f (AsP p) = foldMap f p
foldMap f (ConP g ps) = foldMap f ps
foldMap f (ViewP e p) = foldMap f e `mappend` foldMap f p
foldMap _ _ = mempty
instance Traversable f => Traversable (Pat b f) where
traverse _ VarP = pure VarP
traverse _ WildP = pure WildP
traverse f (AsP p) = AsP <$> traverse f p
traverse f (ConP g ps) = ConP g <$> traverse f ps
traverse f (ViewP e p) = ViewP <$> traverse f e <*> traverse f p
instance Bound (Pat b) where
VarP >>>= _ = VarP
WildP >>>= _ = WildP
AsP p >>>= f = AsP (p >>>= f)
ConP g ps >>>= f = ConP g (ps >>>= f)
ViewP e p >>>= f = ViewP (e >>= f) (p >>>= f)
-- ** Pats
eqPats :: (Eq1 f, Eq a) => Pats bs f a -> Pats bs' f a -> Bool
eqPats NilP NilP = True
eqPats (p :> ps) (q :> qs) = eqPat p q && eqPats ps qs
eqPats _ _ = False
instance Eq1 f => Eq1 (Pats bs f) where (==#) = eqPats
instance (Eq1 f, Eq a) => Eq (Pats bs f a) where (==) = eqPats
instance (Show1 f, Show a) => Show (Pats bs f a) where showsPrec = showsPrec1
instance Show1 f => Show1 (Pats bs f) where
showsPrec1 _ NilP = showString "NilP"
showsPrec1 d (p :> ps) = showParen (d > 5) $
showsPrec1 6 p . showString " :> " . showsPrec1 5 ps
instance Functor f => Functor (Pats bs f) where
fmap _ NilP = NilP
fmap f (p :> ps) = fmap f p :> fmap f ps
instance Foldable f => Foldable (Pats bs f) where
foldMap f (p :> ps) = foldMap f p `mappend` foldMap f ps
foldMap _ _ = mempty
instance Traversable f => Traversable (Pats bs f) where
traverse f NilP = pure NilP
traverse f (p :> ps) = (:>) <$> traverse f p <*> traverse f ps
instance Bound (Pats bs) where
NilP >>>= _ = NilP
(p :> ps) >>>= f = (p >>>= f) :> (ps >>>= f)
-- ** Path into Pats
eqMPath :: MPath is -> MPath js -> Bool
eqMPath (H m) (H n) = eqPath m n
eqMPath (T p) (T q) = eqMPath p q
eqMPath _ _ = False
instance Eq (MPath is) where (==) = eqMPath
compareMPath :: MPath is -> MPath js -> Ordering
compareMPath (H m) (H n) = comparePath m n
compareMPath (H _) (T _) = LT
compareMPath (T p) (T q) = compareMPath p q
compareMPath (T _) (H _) = GT
instance Ord (MPath is) where compare = compareMPath
instance Show (MPath is) where
showsPrec d (H m) = showParen (d > 10) $ showString "H " . showsPrec 11 m
showsPrec d (T p) = showParen (d > 10) $ showString "T " . showsPrec 11 p
-- instance Read (MPath is)
-- ** Path into Pat
eqPath :: Path i -> Path j -> Bool
eqPath V V = True
eqPath L L = True
eqPath (R m) (R n) = eqPath m n
eqPath (C p) (C q) = eqMPath p q
eqPath _ _ = False
instance Eq (Path i) where (==) = eqPath
comparePath :: Path i -> Path j -> Ordering
comparePath V V = EQ
comparePath V _ = LT
comparePath L V = GT
comparePath L L = EQ
comparePath L _ = LT
comparePath (R _) V = GT
comparePath (R _) L = GT
comparePath (R m) (R n) = comparePath m n
comparePath (R _) (C _) = LT
comparePath (C p) (C q) = compareMPath p q
comparePath (C _) _ = GT
instance Ord (Path i) where
compare V V = EQ
compare L L = EQ
compare L _ = LT
compare (R _) L = GT
compare (R m) (R n) = compare m n
compare (C p) (C q) = compare p q
instance Show (Path i) where
showsPrec _ V = showString "V"
showsPrec _ L = showString "L"
showsPrec d (R m) = showParen (d > 10) $ showString "R " . showsPrec 11 m
showsPrec d (C p) = showParen (d > 10) $ showString "C " . showsPrec 11 p
-- |
-- >>> let_ [("x",Var "y"),("y",Var "x" :@ Var "y")] $ lam (varp "z") (Var "z" :@ Var "y")
-- Let (fromList [Scope (Var (B 1)),Scope (Var (B 0) :@ Var (B 1))]) (Scope (Lam VarP (Scope (Var (B V) :@ Var (F (Var (B 1)))))))
--
-- >>> lam (varp "x") (Var "x")
-- Lam VarP (Scope (Var (B V)))
--
-- >>> lam (conp "Hello" [varp "x", wildp]) (Var "y")
-- Lam (ConP "Hello" (VarP :> WildP :> NilP)) (Scope (Var (F (Var "y"))))
main :: IO ()
main = return ()