3

So this is my assignment here in which i have to program the associativity of some expressions, I worked on this a few hours and I'm just missing something obvious. Here are my final two ideas that both somewhat work yet cannot evaluate truly equal expressions properly (The first one gives a parse error) I cannot understand what is wrong. Help :(

    data Expr = Const Int | Add Expr Expr deriving Show
    instance Num Expr where
        fromInteger = Const . fromInteger
        (+) = Add
   -- I have to write here
    instance Eq Expr where 
(Const i) == (Const j) = i == j
(Add i j) == (Add a b) = i == a && j == b || i ==b && j == a
(==) (Add e3 (Add e1 e2)) (Add (Add e4 e5) e6) = 
    (Add(Add e1 e2) e3)==(Add e1 (Add e2 e3)) 
    _ == _ = False
Fatalgoddess
  • 119
  • 1
  • 8
  • Can you show the parse error? – Idris Jun 30 '14 at 14:22
  • Parse error in pattern y + z – Fatalgoddess Jun 30 '14 at 14:23
  • 1
    @Fatalgoddess The problem is that you can't construct a pattern with `+`, since patterns can only be formed from data constructors, variables, and literals. `+` is a function, the compiler doesn't have special knowledge about it in order to understand what `x + y` means as a pattern. – bheklilr Jun 30 '14 at 14:25
  • Cant figure out how to do it differently .. (Const i) == (Const j) = i == j (Add e1 e2) == (Add e3 e4) = e1 == e3 && e2 == e4 _ == _ = False also gives errors – Fatalgoddess Jun 30 '14 at 14:30
  • 1
    your second idea looks like it's on the right track. But you should move the catch-all pattern `_ == _` to the bottom, right now it will prevent any of the other matches from being considered – cdk Jun 30 '14 at 14:30

1 Answers1

4

You might want to replace:

 (==) (Add e3 (Add e1 e2)) (Add (Add e4 e5) e6) = (Add(Add e1 e2) e3)==(Add e1 (Add e2 e3)) 

by

(==) (Add e1 (Add e2 e3)) e = (Add(Add e1 e2) e3) == e
(==) e (Add e1 (Add e2 e3)) = e == (Add(Add e1 e2) e3)

Each equation simply rebalances one expression tree to obtain a left recursion, without trying to check if the expressions are actually equals, so you need a third equation:

   (==) (Add e1 e2 ) (Add e3 e4) = (e1 == e3) && (e2 == e4)

Then I define a function which explicitely takes Expr as parameters to test (==):

testexpr :: Expr -> Expr -> Bool
testexpr a b = a == b

and testexpr (1 + (2 +3)) ((1 + 2) + 3) yields True.

Since it is an assignment, integrating that change in your code, and reorganizing it to make it work is left as an exercise.

didierc
  • 14,572
  • 3
  • 32
  • 52
  • Thankf or taking your time I think I might have even understood what to do wrong since your answer seems logical the tests I have here wont run though and maybe im getting it all wrong – Fatalgoddess Jun 30 '14 at 15:04