2012-01-21 19 views
10

我想在Haskell中做一個簡單的Scheme解釋器。作爲其中的一部分,我正在實現一些原始運算符,如數字,字符串?等Haskell函數需要一個類型和值,並檢查值是否具有該類型

我有這樣的代碼:

isNumber :: [LispVal] -> LispVal 
isNumber ([Number n]) = Bool True 
isNumber   _ = Bool False 

isString :: [LispVal] -> LispVal 
isString ([String n]) = Bool True 
isString   _ = Bool False 

而我想是一樣的東西

isType :: ?? -> [LispVal] -> LispVal 
isType (typeName [typeName n]) = Bool True 
isType      _ = Bool False 

換句話說,我想通過創建ISNUMBER相當於說「isType號碼」。這可能以某種方式嗎?我努力在Google中找到類似的東西,也許是因爲我不知道該怎麼稱呼這種情況。

+4

你可能應該說「構造函數」而不是「類型」,因爲正如它所寫,這個問題在Haskell的上下文中甚至沒有意義。您使用Haskell構造函數來表示Lisp類型,但這與Haskell的結果無關。 – ehird

+0

Data.Typeable可能值得一看,但似乎並不需要動態檢查。 – ExternalReality

+1

請參閱此處[模板Haskell解決方案](http://stackoverflow.com/questions/7213974/how-to-examine-a-quoted-data-constructor-name-in-template-haskell/7214422#7214422)。有了這個,你可以做'isNumber = $(isA'Number)' – hammar

回答

8

我假設你有一個類型是這樣的:

data LispVal = String String | Number Double -- &c.... 

...你想測試一個LispVal值是否是一個特殊的構造函數(StringNumber,&角)基於一些論據。

不幸的是,這並不是一種簡單直接的方法。

你可以訴諸字符串比較:

getTypeName :: LispVal -> String 
getTypeName (String _) = "String" 
getTypeName (Number _) = "Number" 

isType :: String -> [LispVal] -> LispVal 
isType name [val] = Bool (name == getTypeName val) 
isType _ _ = Bool False 

或者你可以比較類型的兩個LispVal S:

sameType :: LispVal -> LispVal -> LispVal 
sameType (String _) (String _) = Bool True 
sameType (Number _) (Number _) = Bool True 
sameType _ _ = Bool False 

...然後創建一個虛擬價值與來比較isType

你也可以做一個「類型」的價值和實現一種反射對LispVal s,則比較根據這些:

data LispType = LispString | LispNumber | LispType 

getType :: LispVal -> LispVal 
getType (String _) = Type LispString 
getType (Number _) = Type LispNumber 
getType (Type _) = Type LispType 

isType :: LispVal -> [LispVal] -> LsipVal 
isType t [v] = isEqual t (getType v) 
isType _ _ = Bool False 

這些方法之一的一些變化可能是你最好的選擇。還有其他方法,基於Haskell的更高級特性,但除非解釋型語言的類型與Haskell的類型更加緊密,否則它們可能不值得這樣麻煩。

+0

使用'C {}'模式語法可能是'getType'減少樣板的好主意。 (同樣適用於'getTypeName'和'sameType'。) – ehird

+2

'getType(Type _)= Type LispType' ...類型的類型是類型類型嗎? O_O? –

+0

謝謝你的優秀回覆!我認爲第二種選擇現在是最容易的。它仍然需要比我希望的更明確的模式匹配,但至少會爲我節省幾行。 –

相關問題