Reputation:
I'm trying to write a function that evaluates a nested boolean data type. My issue comes from comparing a data type within a data type. The first two (Lit and Or) compile fine but I don't understand how to incorporate the first type into the function of the SecondExpr. As I type it out, I feel like I'm taking the longest way possible when something shorter works.
Here are the two data types.
data Expr = Val Int
| Add Expr Expr
| Sub Expr Expr
| Mul Expr Expr
| Div Expr Expr
| If SecondExpr Expr Expr
data SecondExpr = Lit Bool
| Or SecondExpr SecondExpr
| EqualTo Expr Expr
| LessThan Expr Expr
(Another issue I'm having is creating examples of SecondExpr to test because, conceptually, I see every Expr as the 6 different types of Expr. That means, for every Expr Expr there would be hundreds of guards.)
Below is the code so far:
eval :: SecondExpr -> Bool
eval (Lit n) = n
eval (Or e1 e2)
| True && True = True
| True && False = True
| False && True = True
| otherwise = False
eval (EqualTo e1 e2)
| (Add e1 e2) == (Add e1 e2) = True
| (Sub e1 e2) == (Sub e1 e2) = True
| (Mul e1 e2) == (Mul e1 e2) = True
| (Div e1 e2) == (Div e1 e2) = True
| otherwise = False
eval (LessThan e1 e2)
| (Add e1 e2) == (Add e1 e2) = True
| (Sub e1 e2) == (Sub e1 e2) = True
| (Mul e1 e2) == (Mul e1 e2) = True
| (Div e1 e2) == (Div e1 e2) = True
| otherwise = False
This is the error I get:
* No instance for (Eq Expr) arising from a use of `=='
* In the expression: (Add e1 e2) == (Add e1 e2)
In a stmt of a pattern guard for
an equation for `eval':
(Add e1 e2) == (Add e1 e2)
In an equation for `eval':
eval (EqualTo e1 e2)
| (Add e1 e2) == (Add e1 e2) = True
| (Sub e1 e2) == (Sub e1 e2) = True
| (Mul e1 e2) == (Mul e1 e2) = True
| (Div e1 e2) == (Div e1 e2) = True
| otherwise = False
|
24 | | (Add e1 e2) == (Add e1 e2) = True
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
So I know my syntax is wrong but how do you substitute an Expression within the function of an Expression?
Upvotes: 0
Views: 120
Reputation: 85767
You're going to need two evaluation functions:
evalNum :: Expr -> Int
and
evalBool :: SecondExpr -> Bool
Neither of them should use any guards (| ...
).
For example, evalBool
would look like this:
evalBool (Lit n) = n
evalBool (Or e1 e2) = evalBool e1 || evalBool e2
evalBool (EqualTo e1 e2) = evalNum e1 == evalNum e2
evalBool (LessThan e1 e2) = evalNum e1 < evalNum e2
Subexpressions are evaluated recursively with their corresponding eval
functions, and the results are combined using appropriate Haskell operators (such as ||
, ==
, <
).
Implementing evalNum
is left as an exercise for the reader.
Upvotes: 4