
On Sat, Dec 05, 2009 at 05:58:25PM +0000, John Moore wrote:
Hi Brent, Sorry about the confusion below is the whole program, which may help or not? What i want to do is when the program prints out the answers , I would like it to be able to automatically by use of a function indent the answers depending how far down the answer goes.
OK, I think I understand what you want to do, although I'm not exactly clear on how you want the indentation to work. Anyway, I've interspersed my comments in the code below.
import Maybe
Just FYI, "Maybe" is the old Haskell-98 name for the module, but nowadays the standard name is "Data.Maybe".
data Expression = Val Float | Add Expression Expression | Subtract Expression Expression | Multiply Expression Expression | Divide Expression Expression | Let String Expression Expression | Var String deriving Show type Dict =[(String,Expression)] emptyDict :: Dict emptyDict = [] addEntry :: String->Expression ->Dict -> Dict addEntry n e d = (n,e): d lookupEntry :: String -> Dict -> Maybe Expression lookupEntry n [] = Nothing lookupEntry n (x:xs) = if (n == k) then (Just v) else lookupEntry n xs where (k,v) = x
I would write lookupEntry as follows: lookupEntry _ [] = Nothing lookupEntry n ((k,v):xs) | n == k = Just v | otherwise = lookupEntry n xs Note that you can do a nested pattern match ((k,v):xs), and the use of guards instead of if...then...else. But actually, lookupEntry is already in the standard Prelude, it is called 'lookup'! So no need to reimplement it yourself.
evalIO :: Dict -> Expression -> IO Float
This function is rather poor Haskell style, because it mixes up two separate things: evaluating the expression, and printing the result. Instead, I would do something like this: eval :: Dict -> Expression -> ([String], Double) where the output is the result paired with a "trace". (Note I have used Double, a double-precision floating point number, instead of Float, which is single-precision; there's usually very little reason to use Float instead of Double.) Given eval, you can recover evalIO as follows: evalIO :: Dict -> Expression -> IO Double evalIO d e = do let (trace, result) = eval d e mapM_ putStrLn trace return result But this is a lot nicer because it cleanly separates the evaluation from the IO, and you can now do anything you like with the trace --- print it to a file, process it further, etc; you are not tied down to printing it on the screen. Now, if you just want the indentation to increase at each step, like so xxxxx xxxxx xxxxx xxxxx xxxxx ... then you can also separate this out: just return a trace with no indentation, and then apply a function to the trace to indent successive lines, something like zipWith (++) (map (flip replicate ' ') [0..]) trace If, on the other hand, you want the indentation to correspond to how "deep" within the expression the evaluation is taking place, then you can recursively pass along an extra parameter to your evaluation function, like so: eval :: Dict -> Expression -> ([String], Double) eval d e = evalIndented 0 d e where evalIndented i d (Val x) = ([], x) evalIndented i d (Add x y) = let (tx, vx) = evalIndented (i+1) d x (ty, vy) = evalIndented (i+1) d y in (replicate i ' ' ++ "Add " ++ show vx ++ " and " ++ show vy, vx + vy) ...and so on. I hope this is helpful! -Brent

Am Samstag 05 Dezember 2009 21:09:01 schrieb Brent Yorgey:
If, on the other hand, you want the indentation to correspond to how "deep" within the expression the evaluation is taking place, then you can recursively pass along an extra parameter to your evaluation function, like so:
eval :: Dict -> Expression -> ([String], Double) eval d e = evalIndented 0 d e where evalIndented i d (Val x) = ([], x) evalIndented i d (Add x y) = let (tx, vx) = evalIndented (i+1) d x (ty, vy) = evalIndented (i+1) d y in (replicate i ' ' ++ "Add " ++ show vx ++ " and " ++ show vy, vx + vy)
...and so on.
I would even suggest eval :: Dict -> Expression -> ([(Int,String)],Double) eval d e = evalIndented 0 d e where evalIndented _ _ (Val x) = ([],x) evalIndented i d (Add x y) = let ... in ((i,"Add " ++ show vx ++ " and " ++ show vy):tx ++ ty, vx + vy) ... then you can easily extract the traces of subexpressions at a given depth and print those with adjusted indentation and change indentation schemes (indent two/four spaces further per level).
participants (2)
-
Brent Yorgey
-
Daniel Fischer