packages feed

rebound-0.1.0.0: src/Rebound/MonadNamed.hs

-- |
-- Description: Monads supporting scopes of names
-- Stability: experimental
--
-- This is a simplified version of 'Rebound.MonadScoped.MonadScopedReader',
-- where the environment is restricted to a vector of names.

module Rebound.MonadNamed
  ( Sized (..),
    S.MonadScopedReader,
    Scope,
    ScopedReader (..),
    ScopedReaderT (..),
    scope,
    pushVec,
    push,
    LocalName (..),
    runScopedReader,
    runScopedReaderT,
  )
where

import Rebound hiding (fromVec)
import Data.SNat as SNat
import Data.Vec as Vec
import qualified Rebound.MonadScoped as S
import Rebound.MonadScoped (MonadScopedReader(..))
import Data.LocalName

-----------------------------------------------------------------------
-- Scopes
-----------------------------------------------------------------------

-- | A mapping from variables in scope to a name.
newtype Scope name n = Scope {names :: Vec n name}
  deriving (Eq, Show)

emptyScope :: Scope name Z
emptyScope = Scope VNil

fromVec :: Vec p name -> Scope name p
fromVec v = Scope v

extendScope ::
  forall p n name.
  (SNatI p) =>
  Vec p name ->
  Scope name n ->
  Scope name (p + n)
extendScope v (Scope s) = Scope $ Vec.append v s

-----------------------------------------------------------------------
-- MonadScoped class
-----------------------------------------------------------------------

-- | Get the name of variables in scope.
scope :: MonadScopedReader (Scope name) m => m n (Vec n name)
scope = readerS names

-- | Add a new variable to the scope.
push :: (MonadScopedReader (Scope name) m)
  => name -> m (S n) a -> m n a
push n = localS (extendScope (n ::: VNil))

-- | Add a vector of new variables to the scope.
pushVec :: (MonadScopedReader (Scope name) m)
  => Vec p name -> m (p + n) a -> m n a
pushVec v = withSNat (vlength v) $ localS (extendScope v)

-----------------------------------------------------------------------
-- ScopedReader monad
-----------------------------------------------------------------------

-- | A monad transformer to keep track of the name of variables in scope.
type ScopedReaderT name m n a = S.ScopedReaderT (Scope name) m n a

-- | A monad to keep track of the name of variables in scope.
type ScopedReader name n a = S.ScopedReader (Scope name) n a

-- | Run the computation with the provided vector of names.
runScopedReaderT :: forall m n name a. ScopedReaderT name m n a -> Vec n name -> m a
runScopedReaderT c v = S.runScopedReaderT c (Scope v)

-- | Run the computation with the provided vector of names.
runScopedReader :: forall n name a. ScopedReader name n a -> Vec n name -> a
runScopedReader c v = S.runScopedReader c (Scope v)