-----------------------------------------------------------------------------
-- |
-- Module      :  Bound
-- Copyright   :  (C) 2012 Edward Kmett
-- License     :  BSD-style (see the file LICENSE)
--
-- Maintainer  :  Edward Kmett <ekmett@gmail.com>
-- Stability   :  experimental
-- Portability :  portable
--
-- We represent the target language itself as an ideal monad supplied by the
-- user, and provide a 'Scope' monad transformer for introducing bound variables
-- in user supplied terms. Users supply a 'Monad' and 'Traversable' instance, and we
-- traverse to find free variables, and use the 'Monad' to perform substitution
-- that avoids bound variables.
--
-- An untyped lambda calculus:
--
-- > import Bound
-- > import Prelude.Extras
--
-- > infixl 9 :@
-- > data Exp a = V a | Exp a :@ Exp a | Lam (Scope () Exp a)
-- >  deriving (Eq,Ord,Show,Read,Functor,Foldable,Traversable)
--
-- > instance Eq1 Exp   where (==#)      = (==)
-- > instance Ord1 Exp  where compare1   = compare
-- > instance Show1 Exp where showsPrec1 = showsPrec
-- > instance Read1 Exp where readsPrec1 = readsPrec
-- > instance Applicative Exp where pure = V; (<*>) = ap
--
-- > instance Monad Exp where
-- >   return = V
-- >   V a      >>= f = f a
-- >   (x :@ y) >>= f = (x >>= f) :@ (y >>= f)
-- >   Lam e    >>= f = Lam (e >>>= f)
-- >
-- > lam :: Eq a => a -> Exp a -> Exp a
-- > lam v b = Lam (abstract1 v b)
--
-- > whnf :: Exp a -> Exp a
-- > whnf (f :@ a) = case whnf f of
-- >   Lam b -> whnf (instantiate1 a b)
-- >   f'    -> f' :@ a
-- > whnf e = e
--
----------------------------------------------------------------------------
module Bound
  (
  -- * Scopes introduce bound variables in user terms
    Scope(..)
  -- ** Abstraction over bound variables
  , abstract, abstract1
  -- ** Instantiation of bound variables
  , instantiate, instantiate1
  -- * Combinators for manipulating user terms
  , substitute
  , isClosed
  , closed
  -- * Structures permitting substitution
  , Bound(..)
  , (=<<<)
  -- ** Conversion to Traditional de Bruijn
  , Var(..)
  , fromScope
  , toScope
  -- ** Advanced substitution combinators
  , splat
  , mapBound, mapScope
  , liftMBound, liftMScope
  , foldMapBound, foldMapScope
  , traverseBound_, traverseScope_
  , mapMBound_, mapMScope_
  , traverseBound, traverseScope
  , mapMBound, mapMScope
  ) where

import Bound.Var
import Bound.Class
import Bound.Scope
import Bound.Term