The following defines a simple language (strings in ``...'' are terminals):
<Request> ::= <Request0> | <Request1>`` ''Write an interactive program that accepts <Request>s one per input line and processes them while keeping as internal state a stack of output channel descriptions of typeString
<Request0> ::= ``Close
'' | ``Stop
''
<Request1> ::= ``Open
'' | ``Append
''
Maybe String
,
where the topmost element of that stack should be considered as
active.
In the start state, Nothing
is the only stack element and therefore active;
Nothing
should be interpreted as stdout
,
and Just p
as file name p
.
``Open
filename'' should push
the file with name ``filename''
as new active output description.
``Append
any_string'' should append the line
``any_string''
to the current output channel.
``Close
'' should close the current output channel
i.e.,
remove it from the stack.
``Stop
'' terminates interaction.
Produce a control message after every action and pay attention to complete error handling.
> data STFun s x = STFun (s -> (s,x))
Functor
and Monad
for STFun s
and prove the respective laws.
> clift :: (s -> s) -> STFun s () > clift1 :: (s -> a -> s) -> a -> STFun s () > clift2 :: (s -> a -> b -> s) -> a -> b -> STFun s () > clift3 :: (s -> a -> b -> c -> s) -> a -> b -> c -> STFun s () > rlift :: (s -> r) -> STFun s r > rlift1 :: (s -> a -> r) -> a -> STFun s r > rlift2 :: (s -> a -> b -> r) -> a -> b -> STFun s r > rlift3 :: (s -> a -> b -> c -> r) -> a -> b -> c -> STFun s r
STFM
defining an abstract data type STFM a b r
wrapping
STFun (FiniteMap a b) r
and exporting also access functions for sequential access to the
FiniteMap
hidden inside STFM
,
without ever providing direct external access to that FiniteMap
.
Transfer also the instance of Functor
and Monad
from STFun
to STFM
.
The following type declarations define a simple imperative programming
language ---
programs are of type [Com]
,
where every command
either assigns the value of an expression to a variable (Assign
),
or assigns the next value from the input stream to a variable (Read
),
or appends the value of an expression to the output stream (Write
),
or is a While
loop.
The While
loop should be terminated
if its first argument assumes the value ``0''.
Expressions are standard arithmetic expressions
that can also refer to the values of variables (Ref
).
> data Com = Assign Var Exp > | Read Var > | Write Exp > | While Exp [Com] > type Var = String > data Exp = Ref Var > | Num Integer > | Bin BinOp Exp Exp > data BinOp = Plus > | Minus > | Times > | Div
Write an interpreter for this programming language:
> interpret :: [Com] -> [Integer] -> [Integer]This interpreter takes a program and a list of input values available to
Read
as arguments and maps them to
the list of the output values produced by Write
.
For managing the variable environment, use the monad STFM
from problem 2!
If you really cannot get started, you find a skeleton in Interp.xhs.
interpreter :: IO ()
similar to hugs
for interpret
.Declare instances of Read
and Show
for
type Prog = [Com]geared towards a ``normal'' text representation of programs.
Hint: Define appropriate instances of Show
and Read
for the types BinOp
, Exp
and Com
.
Pay attention to instantiate
showList
and readList
for Com
in a useful way.
Extend your I/O interface so that you can at least
Read
),