2012-01-21 17 views
10

türünde olup olmadığını kontrol eder Haskell'de basit bir Scheme yorumlayıcısı yapmaya çalışıyorum. Bunun bir parçası olarak, sayı gibi bazı ilkel operatörleri uyguluyorum, string? vbHaskell işlevi bir tür ve bir değer alır ve değerin

bu gibi bir kod vardır:

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

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

Ya İsterdim ben tarafından ISNUMBER eşdeğer oluşturmak istiyorum, başka deyişle

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

gibi bir şey "isType Numarası". Bu bir şekilde mümkün mü? Google’da benzer bir şey bulmaya çalışıyorum, belki de durumu nasıl arayacağımı bilmiyorum.

+4

Muhtemelen yazdığı gibi, bu sorunun Haskell bağlamında anlam ifade etmediğinden, muhtemelen "tür" yerine "yapıcı" demelisiniz. Haskell kurucuları ile Lisp türlerini temsil ediyorsunuz, ancak bu sonuçla sonuçlanan Haskell sorusuyla doğrudan alakalı değil. – ehird

+0

Data.Typeable bir göz atmaya değer olabilir, ancak burada dinamik kontrollere ihtiyacınız olduğu görünmüyor. – ExternalReality

+1

[Şablon Haskell çözümü] için buraya bakın (http://stackoverflow.com/questions/7213974/how-to-examine-a-quoted-data-constructor-name-in-template-haskell/7214422#7214422). Bununla, 'isNumber = $ (isA 'Number)' – hammar

cevap

8

Ben böyle bir tip şey var sanıyorum:

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

... ve bir LispVal değer, belirli bir yapıcı olup olmadığını test eden bir işlev istiyorum (String, Number, & c.) bazı argüman dayanarak.

Maalesef bunu yapmak için basit, genel bir yol yoktur.

Sen dize karşılaştırmaları başvurmak olabilir:

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

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

Yoksa iki LispVal s tiplerini karşılaştırabilirsiniz:

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

... sonra isType için karşılaştırmak için bir kukla değer yaratmak .

Ayrıca "tip" değerini yapmak ve LispVal s yansıma bir çeşit uygulamak, daha sonra bu dayalı karşılaştırın:

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 

bu yaklaşımların biri üzerinde bazı varyasyon muhtemelen en iyi seçenektir. Haskell'in daha gelişmiş özelliklerine dayanan başka yollar da vardır, fakat yorumlanmış dilin türleri, Haskell'in türlerine çok daha yakın bir şekilde bağlanmadıkça güçlük çekmeye değer değildir.

+0

yapabilirsiniz 'C {}' desen sözdizimini kullanmak, 'getType' için klişeyi azaltmak için iyi bir fikir olabilir. (Aynı "getTypeName" ve "sameType" için de geçerli.) – ehird

+2

'getType (Tür _) = LispType yazın ... türün türü tür tipidir? o_O? –

+0

Mükemmel yanıt için teşekkür ederiz! İkinci seçenek şu an için en kolay olacak. Yine de umduğumdan biraz daha açık bir desen eşleşmesine ihtiyacı var, ama en azından birkaç satır kurtaracak. –

İlgili konular