繁体   English   中英

f#中的循环类型引用

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM