[Haskell-cafe] A Strict GCL Interpreter in Haskell

Tillmann Rendel rendel at cs.au.dk
Thu Jul 2 19:05:39 EDT 2009


Hi Hector,

Hector Guilarte wrote:
> I did that already, but it didn't work... Also, since this kind of error would be a run time error in my GCL Language, I don't want it to continue executing whenever an error is found, that's why I changed it back to just:
> evalExpr:: Expr -> Tabla -> Int
> 
> Instead of using the Either String Int...

I think you misunderstand something.

If you use (Expr -> Table -> Int), you are announcing:
Whatever happens, I keep executing.

If you use (Expr -> Table -> Either String Int), you are announcing:
I may stop earlier because of some problem.

Since may you want to stop earlier, you should use the second type.


Let's look at a very small example, an interpreter for the following 
little language:

   data Expression
     = Literal Integer
     | Add Expression Expression
     | Divide Expression Expression

Because of division by zero, an interpreter for this language may fail. 
So we have two kinds of return values: Sometimes we return a number, and 
sometimes we return an DivideByZero error. We can reflect that in a 
datatype:

   data Result
     = Number Integer
     | DivideByZeroError

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.

   Tillmann


More information about the Haskell-Cafe mailing list