2015-12-30 24 views
1

我正在F#中構建一個解釋器。我試圖聰明地將原始操作符的解釋作爲函數調用(在這種情況下,作爲減少)。如何在字典中編碼不同類型的多個函數

這是想法:

let reduce fx values = 
    Array.reduce values fx 

let primitivesEnv = 
    let r = Dictionary<string,'T -> 'T -> 'T>() 
    r.["int_+"] <- reduce (fun(l:int, r:int) -> l + r) 
    r.["int_-"] <- reduce (fun(l:int, r:int) -> l - r) 
    r 

所以我以後可以做到這一點:

env.["int_+"]([| 1, 2 |]) 

當然,類型檢查拒絕這個與

警告FS0064:此構造使得代碼不如類型註釋所指示的 那樣通用。類型變量'T已被 約束爲類型''a - >'a - >'a'。錯誤FS0001:類型不匹配。 期待一個( '一個 - >' 一 - > '一) - >(' 一個 - > '一 - >' 一) - > '一 - >' 一 - > '一個 但給定一個(' 一個 - > '一 - >' 一) - > 'a'和 '一個將所得類型將 統一時是無限的'(' 一 - > '一 - >' 一) - >「一 - > '一 - > '一個」

PD:我知道如何做到這一點作爲一個簡單的翻譯,而是試圖建立一個解決方案,讓我建立幾十個通用的方式方法,不使爲每一個匹配。

+0

通過簡單的解釋你的意思是大步解釋? – nicolas

+0

我不確定你的意思是「解決方案,讓我以通用的方式構建數十種方法」 有很多種方法來構建解釋器,所以你需要在這裏更精確 – nicolas

+0

如果這裏有python,我可以將函數存儲在一個字典中,並使用它來發送它們。現在F#中我面臨的問題是如何根據值類型進行派發,希望在不編碼所有情況下(所以,我可以爲解釋器準備好F#的內置函數)。 – mamcx

回答

1

首先,有一些問題與您的代碼。您已經添加了一個類型的註釋到您的'T -> 'T -> 'T字典,但在我看來,它應該返回'T[] -> 'T類型的功能,因爲你想給它一個數組和評價的降低。

此外,[| 1, 2 |]是一個元組的數組,你需要多個值的數組,像這樣的:[| 1; 2 |]

我定你這樣的代碼:

let reduce values = 
    Array.reduce values 

let primitivesEnv = 
    let r = System.Collections.Generic.Dictionary<string,'T[] ->'T>() 
    r.["int_+"] <- reduce ((+) : int -> int -> int) 
    r.["int_-"] <- reduce ((-) : int -> int -> int) 
    r 

let result = primitivesEnv.["int_+"] [| 1; 2 |] 

不幸的是,這個ISN問題的結束。

我們可能會說,字典是'T[] ->'T類型,但它不是,在字典中的唯一有效類型爲int[] -> int,第一int -> int -> int類型註釋創建約束。如果我們離開了該類型的註釋,當我們與int[]使用'T被限制爲int

類型參數'T必須始終解決以某種方式固定的類型,它不是一個外卡,讓您使用任何東西。

這意味着直到您想要添加float(或其他類型),除了int之外,字典方法都可以。在使用字典時,唯一的選擇是選擇一種類型或丟棄一些類型安全並在運行時解析特定類型。

最簡單的換做這將是創造一些工會的情況來描述不同類型的減少:

type Reduction = 
    |IntReduction of (int[] -> int) 
    |FloatReduction of (float[] -> float) 

然後創建一個Dictionary<string, Reduction>而不是Dictionary<string,'T[] ->'T>


當談到創造F#的解釋的更一般的問題,我將通過創建一套結構化的可識別聯合來描述所要解釋,這個迷你語言的表達和結構的開始被稱爲抽象語法樹(AST)。

然後,您可以定義一個run函數,該函數遍歷樹並執行AST描述的所有計算。

我也會使用一個解析器組合器庫(我推薦FParsec)來將任何結構化文本解析爲您在上述步驟中定義的聯合案例的抽象語法樹。

Phillip Trelford有一個在線示例如何使用FParsec進行簡單的C#AST:http://www.fssnip.net/lf這可能比您需要的功能強大得多,但希望它能爲您提供一個起點。

+0

我使用熟悉的字典(這是在Python中使用的)。如果存在更好的方法,我願意提出建議。我正在尋找一種調度方法,如果這使得事情更具體一些 – mamcx

+0

@mamcx你不能編寫你的代碼,你可以接受不同類型的參數,這取決於我認爲的字符串的值是你想要做的。你明顯可以通過使用聯合事例或'obj'來完成,並且在運行時檢查類型是否有效,但與完全類型的安全解決方案相比,它顯然缺乏穩健性。如果/完成後你打算如何使用它? – TheInnerLight

+0

這是翻譯 – mamcx

相關問題