{-# OPTIONS_HADDOCK show-extensions #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-| Module : Data.Utils.Stack Description : a simple stack monad Copyright : (c) Lars Brünjes, 2016 License : MIT Maintainer : brunjlar@gmail.com Stability : experimental Portability : portable This module defines the 'StackT' monad transformer, which is simply a wrapped state monad whose state is a list. -} module Data.Utils.Stack ( StackT , pop , peek , push , runStackT , evalStackT , execStackT , Stack , runStack , evalStack , execStack ) where import Control.Monad.Trans.Class (MonadTrans) import Data.MyPrelude -- | A computation of type @'StackT' s m a@ has access to a stack of elements of type @s@. -- newtype StackT s m a = StackT (StateT [s] m a) deriving (Functor, Applicative, Monad, MonadTrans) -- | Peeks at the top element of the stack. Returns 'Nothing' if the stack is empty. -- peek :: Monad m => StackT s m (Maybe s) peek = do xs <- StackT get return $ case xs of [] -> Nothing (x : _) -> Just x -- | Pops the top element from the stack. Returns 'Nothing' if the stack is empty. -- pop :: Monad m => StackT s m (Maybe s) pop = do xs <- StackT get case xs of [] -> return Nothing (x : xs') -> (StackT $ put xs') >> return (Just x) -- | Pushes a new element onto the stack. -- push :: Monad m => s -> StackT s m () push x = StackT $ modify (x :) -- | Runs a computation in the @'StackT' s m@ monad. -- runStackT :: Monad m => StackT s m a -> [s] -> m (a, [s]) runStackT (StackT m) = runStateT m -- | Evaluates a computation in the @'StackT' s m@ monad. -- evalStackT :: Monad m => StackT s m a -> [s] -> m a evalStackT m xs = fst <$> runStackT m xs -- | Executes a computation in the @'StackT' s m@ monad. -- execStackT :: Monad m => StackT s m a -> [s] -> m [s] execStackT m xs = snd <$> runStackT m xs -- | A pure stack monad. -- type Stack s = StackT s Identity -- | Runs a computation in the @'Stack' s@ monad. -- runStack :: Stack s a -> [s] -> (a, [s]) runStack m xs = runIdentity $ runStackT m xs -- | Evaluates a computation in the @'Stack' s@ monad. -- evalStack :: Stack s a -> [s] -> a evalStack m xs = runIdentity $ evalStackT m xs -- | Executes a computation in the @'Stack' s@ monad. -- execStack :: Stack s a -> [s] -> [s] execStack m xs = runIdentity $ execStackT m xs