Я работаю над библиотекой для генерации SQL из выражений LINQ (в основном модифицированное подмножество LINQ-to-SQL). Я использую размеченные союзы для моделирования выражений SQL, но столкнулся с некоторыми (очевидными?) ограничениями. Я хочу сделать что-то вроде следующего (обратите внимание на последнюю строку):
type SqlSourceExpression =
| Table of string
| Join of JoinType * SqlSourceExpression * SqlSourceExpression * SqlExpression //ie, left, right, predicate
and SqlExpression =
| Source of SqlSourceExpression
| OrderBy of SqlExpression * SortDirection
| Select of SqlSourceExpression * SqlExpression * OrderBy list //can't do this
Я мог бы сделать следующее:
type SqlOrderByExpression = SqlExpression * SortDirection
... и измените последние две строки на:
| OrderBy of SqlOrderByExpression
| Select of SqlSourceExpression * SqlExpression * SqlOrderByExpression list
Но это, кажется, имеет две проблемы:
SqlOrderByExpression не является SqlExpression. Это затрудняет использование шаблона посетителя (может быть, здесь и кроется проблема?). Это означает, что при обходе выражения Select я не могу перебирать список порядка с помощью выражений, передающих каждое из них в Visit(expr:SqlExpression).
SqlOrderByExpression — это просто псевдоним типа для кортежа, поэтому информация о типе не сохраняется. Это вредит читабельности IMO.
Есть ли лучший способ смоделировать это? Я попробовал маршрут наследования, но я думаю, что с DU НАМНОГО проще работать (за исключением отмеченной трудности).