Haskell:为什么用户定义枚举的等差数列中需要额外的space?

Haskell: Why is extra space needed in arithmetic sequence for user defined enum?

因此对于 Haskell 中的任何内置类型,我可以构造一个算术序列,就像这个(对于 IntInteger 等)

[1..5]

但是如果我定义一个枚举类型,比如:

data Suit = Club | Diamond | Heart | Spade deriving (Show, Enum) 

当我创建等差数列时,我必须在枚举实例和点号之前包含 space,例如

[Club .. Diamond]

为什么?

问题是,根据 Haskell's lexical rulesmodid.varsym 是对模块中变量的引用。 modid 是由点分隔的 1 个或多个大写标识符的序列,varsym 是符号名称。 Club 是一个有效的 modid 并且 . 是一个有效的 varsym (请注意,在 Prelude 中甚至还有一个具有该名称的运算符,并且可以作为 Prelude..).因此 X.. 被视为模块 X.

中名为 . 的变量的限定名称

所以 Club..Diamond 被标记为 "qualified variable name, constructor name",而不是 "constructor name, dotdot, constructor name"1。当它试图解析限定变量名时,它失败了,因为实际上没有名为 Club.

的模块

[1..5] 不会出现问题,因为 1 不是有效的模块名称,也没有其他方式 1..1. 形成有效的模块名称令牌。请注意,与某些语言不同,1. 不允许作为 1.0 的缩写形式。如果是,您会 运行 陷入类似的问题,因为 1..5 现在将被标记为 "number, dot, number"。但不是,所以不会出现这个问题。


1 "Qualified variable name" 胜过 "constructor name, dotdot" 因为最大 munch 规则,它说当有多种可能性匹配一个标记时,取匹配当前位置最长子串的那个。