packages feed

bound (empty) → 0.1

raw patch · 11 files changed

+745/−0 lines, 11 filesdep +basedep +bifunctorsdep +prelude-extrassetup-changed

Dependencies added: base, bifunctors, prelude-extras, transformers

Files

+ .travis.yml view
@@ -0,0 +1,1 @@+language: haskell
+ Bound.hs view
@@ -0,0 +1,22 @@+-----------------------------------------------------------------------------+-- |+-- Module      :  Bound+-- Copyright   :  (C) 2012 Edward Kmett+-- License     :  BSD-style (see the file LICENSE)+--+-- Maintainer  :  Edward Kmett <ekmett@gmail.com>+-- Stability   :  experimental+-- Portability :  portable+--+----------------------------------------------------------------------------+module Bound+  ( module Bound.Var+  , module Bound.Class+  , module Bound.Scope+  , module Bound.Term+  ) where++import Bound.Var+import Bound.Class+import Bound.Scope+import Bound.Term
+ Bound/Class.hs view
@@ -0,0 +1,34 @@+-----------------------------------------------------------------------------+-- |+-- Module      :  Bound.Class+-- Copyright   :  (C) 2012 Edward Kmett+-- License     :  BSD-style (see the file LICENSE)+--+-- Maintainer  :  Edward Kmett <ekmett@gmail.com>+-- Stability   :  experimental+-- Portability :  portable+--+----------------------------------------------------------------------------+module Bound.Class+  ( Bound(..)+  , (=<<<)+  ) where++infixl 1 >>>=++-- | This may or may not be a monad transformer,+--+-- If it is, then you can use @m >>>= f = m >>= lift . f@+--+-- This is useful for types like expression lists, case alternatives,+-- schemas, etc. that may not be expressions in their own right, but often+-- contain one.++class Bound t where+  (>>>=) :: Monad f => t f a -> (a -> f c) -> t f c+  -- default (>>>=) :: MonadTrans t, Monad f) => t f a -> (a -> f c) -> t f c+  -- m >>>= f = m >>= lift . f++infixr 1 =<<<+(=<<<) :: (Bound t, Monad f) => (a -> f c) -> t f a -> t f c+(=<<<) = flip (>>>=)
+ Bound/Scope.hs view
@@ -0,0 +1,147 @@+-----------------------------------------------------------------------------+-- |+-- Module      :  Bound.Scope+-- Copyright   :  (C) 2012 Edward Kmett+-- License     :  BSD-style (see the file LICENSE)+--+-- Maintainer  :  Edward Kmett <ekmett@gmail.com>+-- Stability   :  experimental+-- Portability :  portable+--+----------------------------------------------------------------------------+module Bound.Scope+  ( Scope(..)+  -- * Abstraction+  , abstract, abstract1+  -- * Instantiation+  , instantiate, instantiate1+  -- * Substitution+  , splat+  -- * Quotienting+  , fromScope+  , toScope+  ) where++import Data.Foldable+import Data.Traversable+import Control.Monad+import Control.Monad.Trans.Class+import Control.Applicative+import Prelude.Extras+import Bound.Class+import Bound.Var++-- | @Scope b f a@ is a an @f@ expression with bound variables in @b@, and free variables in @a@+--+-- This stores bound variables as their generalized de Bruijn representation,+-- in that the succ's for variable ids are allowed to occur anywhere within the tree+-- permitting /O(1)/ weakening and allowing more sharing opportunities. +-- Here the deBruijn 0 is represented by the 'B' constructor of 'Var', while the +-- de Bruijn 'succ' (which may be applied to an entire tree!) is handled by 'F'.+--+-- NB: equality and comparison quotient out the distinct 'F' placements allowed by +-- the choice of a generalized de Bruijn representation and return the same result as a traditional de Bruijn+-- representation would.++newtype Scope b f a = Scope { unscope :: f (Var b (f a)) }++instance Functor f => Functor (Scope b f) where+  fmap f (Scope a) = Scope (fmap (fmap (fmap f)) a)++-- | @toList@ is provides a list (with duplicates) of the free variables+instance Foldable f => Foldable (Scope b f) where+  foldMap f (Scope a) = foldMap (foldMap (foldMap f)) a++instance Traversable f => Traversable (Scope b f) where+  traverse f (Scope a) = Scope <$> traverse (traverse (traverse f)) a++-- | The monad permits substitution on free variables, while preserving bound variables+instance Monad f => Monad (Scope b f) where+  return a = Scope (return (F (return a)))+  Scope e >>= f = Scope $ e >>= \v -> case v of+    B b -> return (B b)+    F ea -> ea >>= unscope . f++instance MonadTrans (Scope b) where+  lift m = Scope (return (F m))++instance (Monad f, Eq b, Eq1 f, Eq a) => Eq  (Scope b f a) where (==) = (==#)+instance (Monad f, Eq b, Eq1 f)       => Eq1 (Scope b f)   where+  a ==# b = liftM Lift2 (fromScope a) ==# liftM Lift2 (fromScope b)+  -- a ==# b = mangleScope a ==# mangleScope b++instance (Monad f, Ord b, Ord1 f, Ord a) => Ord  (Scope b f a) where compare = compare1+instance (Monad f, Ord b, Ord1 f)        => Ord1 (Scope b f) where+  compare1 a b = liftM Lift2 (fromScope a) `compare1` liftM Lift2 (fromScope b)+  -- compare1 a b = compare1 (mangleScope a) (mangleScope b)++mangleScope :: Functor f => Scope b f a -> f (Lift2 Var b (Lift1 f a))+mangleScope (Scope a) = fmap (Lift2 . fmap Lift1) a+{-# INLINE mangleScope #-}++unmangleScope :: Functor f => f (Lift2 Var b (Lift1 f a)) -> Scope b f a+unmangleScope a = Scope (fmap (fmap lower1 . lower2) a)+{-# INLINE unmangleScope #-}+++instance (Functor f, Show b, Show1 f, Show a) => Show  (Scope b f a) where showsPrec = showsPrec1+instance (Functor f, Show b, Show1 f)         => Show1 (Scope b f)   where+  showsPrec1 d a = showParen (d > 10) $ showString "Scope " . showsPrec1 11 (mangleScope a)++instance (Functor f, Read b, Read1 f, Read a) => Read  (Scope b f a) where readsPrec = readsPrec1+instance (Functor f, Read b, Read1 f)         => Read1 (Scope b f) where+  readPrec1 = liftM unmangleScope readPrec1++instance Bound (Scope b) where+  m >>>= f = m >>= lift . f++-- | Capture some free variables in an expression to yield a Scope with bound variables+abstract :: Monad f => (a -> Maybe b) -> f a -> Scope b f a+abstract f e = Scope (liftM k e) where+  k y = case f y of+    Just z  -> B z+    Nothing -> F (return y)+{-# INLINE abstract #-}++-- | Abstract over a single variable+abstract1 :: (Monad f, Eq a) => a -> f a -> Scope () f a+abstract1 a = abstract (\b -> if a == b then Just () else Nothing)+{-# INLINE abstract1 #-}++-- | Enter a scope, instantiating all bound variables+instantiate :: Monad f => (b -> f a) -> Scope b f a -> f a+instantiate k e = unscope e >>= \v -> case v of+  B b -> k b+  F a -> a+{-# INLINE instantiate #-}++-- | Enter a scope with one bound variable, instantiating it+instantiate1 :: Monad f => f a -> Scope () f a -> f a+instantiate1 e = instantiate (\ () -> e)+{-# INLINE instantiate1 #-}+++-- | @fromScope@ quotients out the possible placements of F in Scope+-- distributing them all to the leaves. This yields a traditional deBruijn+-- indexing scheme for bound variables.+--+-- > fromScope . toScope = id+-- > fromScope . toScope . fromScope = fromScope+--+-- @(toScope . fromScope)@ is idempotent+fromScope :: Monad f => Scope b f a -> f (Var b a)+fromScope (Scope s) = s >>= \v -> case v of+  F e -> liftM F e+  B b -> return (B b)+{-# INLINE fromScope #-}++toScope :: Monad f => f (Var b a) -> Scope b f a+toScope e = Scope (liftM (fmap return) e)+{-# INLINE toScope #-}++-- | Perform substitution on both bound and free variables in a scope+splat :: Monad f => (a -> f c) -> (b -> f c) -> Scope b f a -> f c+splat f unbind s = unscope s >>= \v -> case v of+  B b -> unbind b+  F ea -> ea >>= f+{-# INLINE splat #-}
+ Bound/Term.hs view
@@ -0,0 +1,33 @@+-----------------------------------------------------------------------------+-- |+-- Module      :  Bound.Term+-- Copyright   :  (C) 2012 Edward Kmett+-- License     :  BSD-style (see the file LICENSE)+--+-- Maintainer  :  Edward Kmett <ekmett@gmail.com>+-- Stability   :  experimental+-- Portability :  portable+--+----------------------------------------------------------------------------+module Bound.Term+  ( substitute+  , isClosed+  , closed+  ) where++import Data.Traversable+import Data.Maybe (isJust)++-- | @substitute p a w@ replaces the free variable @a@ with @p@ in @w@+substitute :: (Monad f, Eq a) => f a -> a -> f a -> f a+substitute p a w = w >>= \b -> if a == b then p else return b+{-# INLINE substitute #-}++-- | If a term has no free variables, you can freely change the type of free variables it uses+closed :: Traversable f => f a -> Maybe (f b)+closed = traverse (const Nothing)+{-# INLINE closed #-}++isClosed :: Traversable f => f a -> Bool+isClosed = isJust . closed+{-# INLINE isClosed #-}
+ Bound/Var.hs view
@@ -0,0 +1,74 @@+-----------------------------------------------------------------------------+-- |+-- Module      :  Bound.Var+-- Copyright   :  (C) 2012 Edward Kmett+-- License     :  BSD-style (see the file LICENSE)+--+-- Maintainer  :  Edward Kmett <ekmett@gmail.com>+-- Stability   :  experimental+-- Portability :  portable+--+----------------------------------------------------------------------------+module Bound.Var (Var(..)) where++import Data.Foldable+import Data.Traversable+import Data.Monoid (mempty)+import Data.Bifunctor+import Data.Bifoldable+import Data.Bitraversable+import Control.Applicative+import Control.Monad (ap)+import Prelude.Extras+import Text.Read++-- | "I am not a number, I am a /free monad/!"+--+-- @Var b a@ represents variables that may either be "bound" (@B@) or "free" (@F@)+data Var b a+  = B b -- this is a bound variable+  | F a -- this is a free variable+  deriving (Eq,Ord,Show,Read)++instance Functor (Var b) where+  fmap _ (B b) = B b+  fmap f (F a) = F (f a)++instance Foldable (Var b) where+  foldMap f (F a) = f a+  foldMap _ _ = mempty++instance Traversable (Var b) where+  traverse f (F a) = F <$> f a+  traverse _ (B b) = pure (B b)++instance Applicative (Var b) where+  pure = F+  (<*>) = ap++instance Monad (Var b) where+  return = F+  F a  >>= f = f a+  B b >>= _ = B b++instance Bifunctor Var where+  bimap f _ (B b) = B (f b)+  bimap _ g (F a) = F (g a)++instance Bifoldable Var where+  bifoldMap f _ (B b) = f b+  bifoldMap _ g (F a) = g a++instance Bitraversable Var where+  bitraverse f _ (B b) = B <$> f b+  bitraverse _ g (F a) = F <$> g a++instance Eq2 Var   where (==##)     = (==)+instance Ord2 Var  where compare2   = compare+instance Show2 Var where showsPrec2 = showsPrec+instance Read2 Var where readPrec2  = readPrec++instance Eq b   => Eq1   (Var b) where (==#)      = (==)+instance Ord b  => Ord1  (Var b) where compare1   = compare+instance Show b => Show1 (Var b) where showsPrec1 = showsPrec+instance Read b => Read1 (Var b) where readPrec1  = readPrec
+ LICENSE view
@@ -0,0 +1,30 @@+Copyright 2012 Edward Kmett++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions+are met:++1. Redistributions of source code must retain the above copyright+   notice, this list of conditions and the following disclaimer.++2. Redistributions in binary form must reproduce the above copyright+   notice, this list of conditions and the following disclaimer in the+   documentation and/or other materials provided with the distribution.++3. Neither the name of the author nor the names of his contributors+   may be used to endorse or promote products derived from this software+   without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE+DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN+ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE+POSSIBILITY OF SUCH DAMAGE.
+ Setup.lhs view
@@ -0,0 +1,7 @@+#!/usr/bin/runhaskell+> module Main (main) where++> import Distribution.Simple++> main :: IO ()+> main = defaultMain
+ bound.cabal view
@@ -0,0 +1,37 @@+name:          bound+category:      Language, Compilers/Interpreters+version:       0.1+license:       BSD3+cabal-version: >= 1.6+license-file:  LICENSE+author:        Edward A. Kmett+maintainer:    Edward A. Kmett <ekmett@gmail.com>+stability:     experimental+homepage:      http://github.com/ekmett/bound/+bug-reports:   http://github.com/ekmett/bound/issues+copyright:     Copyright (C) 2012 Edward A. Kmett+synopsis:      Combinators for manipulating locally-nameless generalized de Bruijn terms+description:   Combinators for manipulating locally-nameless generalized de Bruijn terms++build-type:    Simple+extra-source-files: .travis.yml examples/Simple.hs examples/Exp.hs++source-repository head+  type: git+  location: git://github.com/ekmett/bound.git++library+  build-depends:+    base           >= 4     && < 5,+    bifunctors     >= 0.1.3 && < 0.2,+    prelude-extras >= 0.2   && < 0.3,+    transformers   >= 0.2   && < 0.4++  exposed-modules:+    Bound+    Bound.Class+    Bound.Scope+    Bound.Term+    Bound.Var++  ghc-options: -Wall
+ examples/Exp.hs view
@@ -0,0 +1,308 @@+{-# LANGUAGE StandaloneDeriving #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE UndecidableInstances #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE PolyKinds #-}+{-# LANGUAGE KindSignatures #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE ExistentialQuantification #-}+{-# LANGUAGE TypeOperators #-}+module Exp 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++-- ghci> 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)))))))+--+-- ghc> lam (varp "x") (Var "x")+-- ghc> lam (conp "Hello" [varp "x", wildp])) (Var "y")++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)+  -- | Case (Exp a) [Alt Exp a]++data Alt f a = forall b. Alt (Pat b f a) (Scope (Path b) 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)+ -- Case e as >>= f = Case (e >>= f) (fmap (>>>= f) as)++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+ -- Case e as ==# Case f bs = e ==# f && as == bs+  _         ==# _         = 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++{-+instance Eq1 f => Eq1 (Alt f) where+  Alt p s ==# Alt q t = eqPat p q && s == unsafeCoerce t++instance (Eq1 f, Eq a) => Eq (Alt f) where (==) = (==#)++instance Show1 f => Show1 (Alt f) where+  showsPrec d (Alt p s) = showsPrec d (Alt p s)+-}+++-- * 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++
+ examples/Simple.hs view
@@ -0,0 +1,52 @@+module Simple where++import Data.Foldable+import Data.Traversable+import Control.Monad+import Control.Applicative+import Prelude hiding (foldr)+import Prelude.Extras+import Bound++-- \ x -> x+-- ghci> lam "x" (Var "x")+-- Lam (Var (Bound ()))++-- \ x -> x y+-- ghci> lam "x" (Var "x" :@ Var "y")+-- Lam (Var (Bound ()) :@ Var (Free (Var "y")))++-- \ y -> \x -> x y+-- ghci> lam "y" (lam "x" (Var "x" :@ Var "y"))+-- Lam (Lam (Var (Bound ()) :@ Var (Free (Var (Bound ())))))++infixl 9 :@++data Exp a = Var a | Exp a :@ Exp a | Lam (Scope () Exp a)+  deriving (Eq,Ord,Show,Read)+++lam :: Eq a => a -> Exp a -> Exp a+lam v b = Lam (abstract1 v b)++instance Eq1 Exp      where (==#)      = (==)+instance Ord1 Exp     where compare1   = compare+instance Show1 Exp    where showsPrec1 = showsPrec+instance Read1 Exp    where readsPrec1 = readsPrec+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 e)  = Lam <$> traverse f e++instance Monad Exp where+  return         = Var+  Var a    >>= f = f a+  (x :@ y) >>= f = (x >>= f) :@ (y >>= f)+  Lam e    >>= f = Lam (e >>>= f)