2012-09-07 116 views
2

我正在寫簡單的excel公式給F#中的linq表達式生成器。我使用遞歸表達式構建器將公式解析爲AST並構建表達式。我stucked上傳遞環境(的(字符串表達式)對地圖)來生成表達在電話:f#中的循環類型引用#

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

凡pexpr解析AST和eval是表達式生成器的功能。

的問題是定義一個類型看起來應該像這樣的:

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

如果pexpr包含在瓦爾的形式參照其他表達式(「名稱」),我想注入的表達,隨着「搜索功能名稱「並將其調用,並在該調用中傳遞相同的環境映射。

不幸的是,編譯說沒有:

這種類型的定義通過的縮寫

涉及即時循環引用有什麼辦法來定義.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