[英]Cyclic type reference in f#
我正在为F#中的linq表达式构建器编写简单的excel公式。 我正在使用递归表达式构建器将公式解析为AST并构建表达式。 我一直坚持将环境((字符串,表达式)映射对)传递给该调用中生成的表达式:
Expression.Lambda<System.Func<double>>(eval pexpr).Compile()
解析pexpr的位置AST和eval是表达式构建函数。
问题是定义类型应该如下所示:
type ExprFunc = Func<ExprFunc map, double>
Expression.Lambda<ExprFunc>(eval pexpr).Compile()
如果pexpr包含对Var(“name”)形式的其他表达式的引用,我想注入在环境映射中使用“name”搜索函数的表达式并调用它,在该调用中传递相同的环境映射。
不幸的是,编译器说不:
此类型定义涉及通过缩写的立即循环引用
有没有办法在.net中定义这样的函数类型?
如果要编写引用自身的类型声明,则不能使用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()
WrappedExprFunc
说一句,如果您正在生成C#表达式树,那么将WrappedExprFunc
定义为类可能更容易,因为这样更容易处理。 这取决于你的其余代码。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.