
Tillmann Rendel wrote:
Now we can write our interpreter:
eval :: Expression -> Result eval (Literal n) = Number n
eval (Add a b) = case eval a of Number result_of_a -> case b of Number result_of_b -> Number (result_of_a + result_of_b)
DivideByZeroError -> DivideByZeroError
DivideByZeroError -> DivideByZeroError
eval (Add a b) = case eval a of Number result_of_a -> case b of Number result_of_b -> if b == 0 then DivideByZeroError else Number (result_of_a + result_of_b)
DivideByZeroError -> DivideByZeroError
DivideByZeroError -> DivideByZeroError
This interpreter will stop as soon as it encounters a division by zero, because we take care to return DivideByZeroError whenever we see a DivideByZeroError in one of the subterms.
So you have to use an appropriate return type (like (Either String Int) or Result), and you have to pattern match on the result of "earlier" parts of your program, and propagate the error.
And of course, these case expression are a case for the error monad. I think that Wadler's paper is a great introduction to writing an interpreter like the one at discussion here Monads for functional programming. Philip Wadler. http://homepages.inf.ed.ac.uk/wadler/papers/marktoberdorf/baastad.pdf Regards, apfelmus -- http://apfelmus.nfshost.com