I am working on it right now as a practical project.
, , . , Haskell:
data Value = BoolValue Bool
| NumberValue Double
| StringValue String
StateT ErrorT IO:
-- | A monad representing a step in an RPL program.
--
-- This type is an instance of 'MonadState', so each action is a function that
-- takes an 'RPLContext' as input and produces a (potentially different)
-- 'RPLContext' as its result. It is also an instance of 'MonadError', so an
-- action may fail (with 'throwRPLError'). And it is built on the 'IO' monad,
-- so 'RPL' computations can interact with the outside world.
type RPL = StateT RPLContext (ErrorT RPLError IO)
-- | Executes an 'RPL' computation.
-- The monadic result value (of type @a@) is discarded, leaving only the final
-- 'RPLContext'.
runRPL :: RPL a -- ^ The computation to run
-> RPLContext -- ^ The computation initial context
-> IO (Either RPLError RPLContext)
-- ^ An 'IO' action that performs the operation, producing either
-- a modified context if it succeeds, or an error if it fails.
runRPL a = runErrorT . (execStateT a)
"" ( ) "", , :
-- | The monadic state held by an 'RPL' computation.
data RPLContext = RPLContext {
contextStack :: Stack, -- ^ The context data stack.
contextEnv :: Env -- ^ The context environment.
}
( , Stack [Value].)
, , , ( StateT RPL). , , :
-- | Pushes a value onto the stack.
pushValue :: Value -> RPL ()
pushValue x = modifyStack (x:)
-- | Transforms the current stack by a function.
modifyStack :: (Stack -> Stack) -> RPL ()
modifyStack f = do
stack <- getStack
putStack $ f stack
-- | Returns the entire current stack.
getStack :: RPL Stack
getStack = fmap contextStack get
-- | Replaces the entire current stack with a new one.
putStack :: Stack -> RPL ()
putStack stack = do
context <- get
put $ context { contextStack = stack }
getStack, putStack modifyStack MonadState get, put modify, RPLContext.
- RPL, , pushValue.
Parsec. .
, RPL, "" 48 ".