2012-05-25 50 views
0

我已經問了the question about undefined。而且因爲不可能做這樣的事情,所以我會描述一下這種情況是否有用。但我認爲這個問題很常見,在其他情況下可能有用。未定義和開發(第2部分)

讓我們想象一種情況,當我們爲某些語法編寫解析器時。我們已經定義了由許多數據類型實現的AST,每個數據類型都有一組構造函數,每個構造函數都有一組參數。每種類型都來自Show。然後我們開始編寫解析器實現,在這裏我們定義了許多具有遞歸依賴關係的函數。

由於我們有很多功能,所以很難一下子寫一個完整的模塊而沒有檢查。但函數循環引用不允許編譯未完成的模塊。在這種情況下,我定義了鉤子函數,它們完全不需要返回所需類型的值。

這是一個問題!函數不能返回一個簡單的類型,而是返回帶構造函數的數據構造函數。這對於一個鉤子函數來說太難了。所以我這樣做:

parseHook _ = undefined 

一切是簡單的結果數據樹,直到「未定義」不是。我想指出,這種情況發生在發展階段,我唯一想要看到的是樹結構。當然,我可以將每種類型都包含在「也許」中,但我不想更改已有的類型。

英語不是我的母語,所以我不確定我是否正確表達了我的想法。這就是爲什麼我要添加這種情況的一個例子:

data StructParam = StructParam Int Int 
       deriving Show 

data Struct1 = Struct1 Int Int StructParam Int Int Int Int StructParam 
      deriving Show 

data Struct2 = Struct2 Int Int StructParam Int Int Int Int StructParam 
      deriving Show 

data Struct3 = Struct3_var1 Struct1 
      | Struct3_var2 Struct2 
      deriving Show 

-- this hook is ok, but too long 
parse1 _ = Struct1 1 2 (StructParam 3 4) 5 6 7 8 (StructParam 9 0) 

-- this hook is short, but undefined 
parse2 _ = undefined 

-- complete function 
rootParse 1 = Struct3_var1(parse1 1)  
rootParse 2 = Struct3_var2(parse2 2) 

>print $ rootParse 1 
Struct3_var1 (Struct1 1 2 (StructParam 3 4) 5 6 7 8 (StructParam 9 0)) 

>print $ rootParse 2 
Prelude.undefined 

-- but I want something like this 
>print $ rootParse 2 
Struct3_var2("undefined") 

回答

10

您可以添加「未實現」在你的數據類型的構造,有在的Unimplemented定義結束全部解析默認情況下,再節目實例將輕鬆工作。

data Exp = Literal Int 
     | Variable String 
     | Operator Op Exp Exp 
     | Unimplemented 

    deriving Show 
+0

我認爲這是最簡單的解決方案,但它有兩個缺點。第一個是我們必須爲當前添加新的構造函數,第二個是我們必須創建一個唯一的Unimplemented構造函數名稱:ExpUnimplemented,StatementUnimplemented等等所有類型。這並不複雜,但有點不方便。 – user1374768

+10

最重要的是,一旦你相信你完成了,你可以刪除構造函數,並且類型檢查器會告訴你是否真的完成了所有的事情。 –

0

一個醜陋的黑客攻擊可能實現這一目標的一個位是爲了檢測由未定義拋出的異常使用unsafePerformIOcatch在這個類的顯示實例。不過,我不會推薦這種方法。