我正在尝试在Haskell中创建一个简单的Scheme解释器。作为其中的一部分,我正在实现一些原始运算符,如数字?,字符串?等
我有这样的代码:
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
换句话说,我想通过说“isType Number”创建等效的isNumber。这有可能吗?我很难在谷歌找到类似的东西,也许是因为我不知道该怎么称呼这种情况。
答案 0 :(得分:8)
我假设你有类似这样的类型:
data LispVal = String String | Number Double -- &c....
...并且您想要一个函数来测试LispVal
值是否是基于某个参数的特定构造函数(String
,Number
和& c。)。
不幸的是,实际上没有一种直截了当的通用方法。
你可以求助于字符串比较:
getTypeName :: LispVal -> String
getTypeName (String _) = "String"
getTypeName (Number _) = "Number"
isType :: String -> [LispVal] -> LispVal
isType name [val] = Bool (name == getTypeName val)
isType _ _ = Bool False
或者你可以比较两个LispVal
的类型:
sameType :: LispVal -> LispVal -> LispVal
sameType (String _) (String _) = Bool True
sameType (Number _) (Number _) = Bool True
sameType _ _ = Bool False
...然后创建一个虚拟值以与isType
进行比较。
您还可以创建“类型”值并对LispVal
实施一种反思,然后根据这些进行比较:
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的类型更紧密地联系在一起,否则它们可能不值得麻烦。