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
| 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

= 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

= 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
```