Haskell函数,它接受一个类型和一个值,并检查value是否具有该类型

时间:2012-01-21 23:24:39

标签: haskell types

我正在尝试在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。这有可能吗?我很难在谷歌找到类似的东西,也许是因为我不知道该怎么称呼这种情况。

1 个答案:

答案 0 :(得分:8)

我假设你有类似这样的类型:

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

...并且您想要一个函数来测试LispVal值是否是基于某个参数的特定构造函数(StringNumber和& 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的类型更紧密地联系在一起,否则它们可能不值得麻烦。