Допустим, я создаю парсер для языка, специфичного для домена, в F #.F # design pattern
Я определил размеченное объединение для представления выражений:
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
Теперь я выстроил AST типа Expression
и хочу сгенерировать код для него. У меня есть одна функция, которая делает вывод типа и тип проверки на выражение.
Он определяется как
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)
...
И у меня есть еще одна функция для генерации кода, который следует той же схеме: Возьмите выражение, писать согласно шаблону заявления для каждого элемента в союзе.
Мой вопрос: Является ли это идиоматическим способом сделать это в F #?
Мне кажется, что было бы более чистым, если бы каждый член союза определил свои собственные InferType
и GenerateCode
локально с ним.
Если бы я использовал C#, я бы определил некоторый абстрактный базовый класс под названием Expression
с виртуальными методами для InferType
и GenerateCode
, а затем переопределить их в каждом подклассе.
Есть ли другой способ сделать это?
Спасибо - это ответ, который я искал , –