Reputation: 83
I have an assigment where I have to program an evaluation function eval::Ast -> String which evaluates any Ast into a string. for example:
>eval (parse "hel + lo")
"hello"
> eval (parse "mi + 2 * la")
"milala"
I've made a parse-function that e.g. takes "hel + lo" and returns Plus (Word "hel") (Word "lo")
But I am very unsure of what the function (and types) should look like as there are multiple types involved in the evaluation of the AST... Anyone who can put me in the right direction?
The AST is defined as
data Ast
= Word String
| Num Int
| Mult Ast Ast
| Plus Ast Ast
| Minus Ast Ast
deriving (Eq, Show)
Upvotes: 1
Views: 383
Reputation: 531205
eval :: AST -> String
is what defines the semantics of your operations. For example, eval (Plus (Word x) (Word y)) == x ++ y
.
However, what should eval (Plus x y)
produce if both arguments are numbers? Should it concatenate them, or add them numerically? What if either one itself is one of the Plus
, Minus
, or Mul
values? You would need to evaluate them first, but then you can't tell if a result like "2"
is really a string, or the result of a number.
You also need to decide if every AST
can be evaluated: does Mul (Word "x") (Word "y")
make sense? If not, what String
would you return?
I would suggest two things:
First, define a simplify
function that takes care of reducing the AST
to something simpler. It will take care of doing things like numerical arithmetic in the case of Plus (Num ...) (Num ...)
, but leave things like Word x
or Plus (Word x) (Num y)
unchanged.
simplify :: AST -> AST
simplify (Num x) = Num x -- Easy case done for you; no simplification necessary
simplify (Word x) = ...
-- Hint: in each of the following, you need to recursively simplify the operands.
-- Once you do that, you can either simplify further, or return a new
-- node to be evaluated.
simplify (Plus x y) = ...
simplify (Minus x y) = ...
simplify (Mul x y) = ...
Second, define eval :: AST -> Either String String
, will first use simplify
on its argument, then do case-by-case conversions of AST
s to Strings
where feasible, and returning an appropriate error message where it isn't.
eval :: AST -> Either String String
eval x = eval' (simplify x)
where eval' (Word x) = Right x -- Easy case done for you
eval' (Num x) = ...
-- simplify will have reduced all the Num + Num, Num - Num, and
-- Num * Num nodes to single Num nodes already.
eval' (Plus (Word x) (Word y)) = x ++ y -- Other easy case done above
eval' (Plus x y) = ...
eval' (Minus (Word x) (Word y)) = ...
eval' (Minus x y) = ...
eval' (Mul (Word x) (Word y)) = ...
eval' (Mul x y) = ...
Note that you could conceivably define some combinations in either eval'
or simplify
, e.g.
simplify (Plus (Word x) (Word y)) == Word $ x ++ y
leaving the more complicated (and possibly impossible) cases to eval
.
Upvotes: 2