所以在我的代码中,我将数据类型Token声明为:
data Token = Char | Int
deriving (Show,Eq,Ord)
和声明为
的函数readIfNumberreadIfNumber :: Char -> Token
readIfNumber a
| isDigit a = Token (digitToInt a)
| otherwise = Token a
但是当我尝试编译时,控制台返回错误"期望类型令牌,但得到了Char"或者"期待令牌,但得到了Int"根据我的Token声明,当Int被视为令牌时。我在这做错了什么?
答案 0 :(得分:7)
在变体类型中,您始终需要明确指出您采用的选项。即你需要使用构造函数明确地“标记”两个分支。像,
data Token = CharToken Char | IntToken Int
当实际从char或int构建一个令牌时,你将它包装在合适的构造函数中:
readIfNumber a
| isDigit a = IntToken $ digitToInt a
| otherwise = CharToken a
需要这个原因吗?好吧,Haskell有完整的type erasure,即在编译时完全跟踪,决定和优化类型。在运行时,您不知道包含的类型是char还是int。有时这没关系,即你有多态行动。例如,length
实际上并不关心列表中包含的元素的类型,因为它只处理列表的结构。
但是,在这种情况下,收到Token
的人需要知道它是char还是int,才能进一步正确处理它。因此需要标记包含哪种类型。