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