Suppose I create a parser for a domain-specific language in F #.
I have defined a discriminatory union to represent expressions:
type Expression = | Equality of Expression*Expression | NonEquality of Expression*Expression | Or of Expression*Expression | And of Expression*Expression | If of Expression*Expression | IfElse of Expression*Expression*Expression | Bool of bool | Variable of string | StringLiteral of string
Now I have created an AST of type Expression and want to generate code for it. I have one function that does type inference and type validation of an expression.
It is defined as
let rec InferType expr = match expr with | Equality(e1,e2) -> CheckTypes (InferType e1) (InferType e2) | Or(e1,e2) -> CheckTypes (InferType e1) (InferType e2) | And(e1,e2) -> CheckTypes (InferType e1) (InferType e2) ...
And I have another function for generating code that follows a similar pattern: Take an expression, write pattern matching statements for each element in the union.
My question is: is this an idiomatic way to do this in F #?
It seems to me that it would be cleaner if each member of the union defined their own InferType and GenerateCode locally with it.
If I were using C #, I would define some abstract base class called Expression with virtual methods for InferType and GenerateCode , and then redefine them in each subclass.
Is there any other way to do this?
f #
Hs. Dec 20 '09 at 17:57 2009-12-20 17:57
source share