2012-09-07 3 views
2

Я пишу простую формулу excel для построителя выражений linq в F #. Я разбираю формулы в AST и строю выражения с использованием рекурсивного выражения. Я stucked при прохождении среды (на карте (строка, выражение) пар) генерируемую выражение в том, что вызов:Циклический тип ссылки в f #

Expression.Lambda<System.Func<double>>(eval pexpr).Compile() 

Где PExpr разбирается АСТ и Eval является функцией Построитель выражений.

Проблема с определением типа, который должен выглядеть следующим образом:

type ExprFunc = Func<ExprFunc map, double> 
Expression.Lambda<ExprFunc>(eval pexpr).Compile() 

Если PExpr содержит ссылку на другое выражение в виде Var («имя»), я хочу, чтобы ввести выражение, которое ищет функцию с " имя "в карте окружения и вызвать его, передавая ту же карту окружения в этом вызове. не

К сожалению, компилятор говорит нет:

Это определение типа предполагает немедленную циклическую ссылку через аббревиатуру

Есть ли способ определить такой тип функции в .net?

ответ

6

Если вы хотите написать объявление типа, которое ссылается на себя, вы не можете использовать псевдоним типа F #. Проблема заключается в том, что F # типа псевдоним стирается во время компиляции, так что рекурсивная ссылка приведет к бесконечному типа:

Func<Func<Func<Func<... map, double> map, double> map, double> map, double> 

В F #, самая простая альтернатива, вероятно, чтобы определить простой дискриминированный союз:

type ExprFunc = EF of Func<ExprFunc map, double> 

Затем вы можете использовать шаблон EF f, чтобы получить базовый делегат в функции F #. Делать это напрямую не будет работать с Expression.Lambda, хотя, так что вам, вероятно, нужно что-то вроде:

type ExprFunc = Func<ExprFunc map, double> 
and WrappedExprFunc = EF of ExprFunc 

Expression.Lambda При вызове, вы должны будете использовать Func<..> делегат в качестве аргумента, но вам нужно модифицировать код в eval правильно обрабатывать завернутые аргументы (которые будут типа WrappedExprFunc):

Expression.Lambda<ExprFunc>(eval pexpr).Compile() 

как и в сторону, если вы генерируете # деревья выражений C, может быть проще определить WrappedExprFunc как класс, потому что это легче обрабатывать. Это зависит от остальной части вашего кода.

+0

Большое спасибо, я попробую это. – rkrahl

Смежные вопросы