
On Wednesday 01 December 2010 20:34:31, John Moore wrote:
Hi , Havent used haskell in a while can someone explain just whats happening here. I know what it does, I just can't workout how it does it. Only need to explain how the red area works and I can work out the rest myself
Regards
John
module Rollback where
data Expression = Val Double
| Add Expression Expression | Subtract Expression Expression | Multiply Expression Expression | Divide Expression Expression
deriving Show demo1 = (Add(Multiply(Divide(Subtract(Val 25)(Val 5))(Val 10))(Val 7))(Val 30))
evalStep reduces the Expression one step unless it's a Val, which is irreducible.
evalStep :: Expression -> Expression evalStep (Val x)= (Val x)
Can't reduce a Val, so leave it as is.
evalStep (Add x y)
For a non-atomic Expression (here Add), look at the first component/left branch (an Expression is a binary tree with Vals at the leaves and arithmetic operations at the branch nodes).
= case x of (Val a) -> case y of
If the left branch is irreducible, look at the right
(Val b) -> Val (a+b)
If that is also irreducible, add the values and return the irreducible Expression
left -> Add x (evalStep y)
otherwise reduce the right branch one step (recur).
right -> Add (evalStep x)y
If the left branch is reducible, reduce it one step (recur), leaving the right unchanged.
evalStep (Subtract x y) = case x of (Val a) -> case y of (Val b) -> Val (a-b) left -> Subtract x (evalStep y) right -> Subtract (evalStep x)y evalStep (Multiply x y) = case x of (Val a) -> case y of (Val b) -> Val (a*b) left -> Multiply x (evalStep y) right -> Multiply (evalStep x)y
evalStep (Divide x y) = case x of (Val a) -> case y of (Val b) -> Val (a/b) left -> Divide x (evalStep y) right -> Divide (evalStep x)y type Stack = [Expression] evaluate :: Expression -> IO () evaluate exp = do stk <- evalWithStack exp [exp] putStrLn "End of Equation"
evalWithStack :: Expression -> Stack -> IO Stack -- Base case evalWithStack (Val a) stk = return stk -- Recursive case evalWithStack e stk = do putStrLn "Evaluating one more step" let e' = (evalStep e) putStrLn ("Result is "++(show e')) putStrLn "Do another step (y/n) or rollback (r)? :" c <- getLine case c of "y" -> evalWithStack e' (e':stk) "r" -> let (a,stk') = stackBack stk in evalWithStack a stk' "n" -> do { putStrLn ("Ok you said :" ++ show c ++ "so that's it " ++ "You went as deep as " ++ show (getCount stk) ++" levels") ; return (e': stk) }
stackBack :: Stack -> (Expression,Stack) stackBack [a] = (a,[a]) stackBack (a:as) = (a,as) stackBack [] = error "Nothing there"
getCount :: Stack -> Int getCount stk = length stk