Haskell:为什么用户定义枚举的等差数列中需要额外的space?
Haskell: Why is extra space needed in arithmetic sequence for user defined enum?
因此对于 Haskell 中的任何内置类型,我可以构造一个算术序列,就像这个(对于 Int
或 Integer
等)
[1..5]
但是如果我定义一个枚举类型,比如:
data Suit = Club | Diamond | Heart | Spade deriving (Show, Enum)
当我创建等差数列时,我必须在枚举实例和点号之前包含 space,例如
[Club .. Diamond]
为什么?
问题是,根据 Haskell's lexical rules,modid.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 规则,它说当有多种可能性匹配一个标记时,取匹配当前位置最长子串的那个。
因此对于 Haskell 中的任何内置类型,我可以构造一个算术序列,就像这个(对于 Int
或 Integer
等)
[1..5]
但是如果我定义一个枚举类型,比如:
data Suit = Club | Diamond | Heart | Spade deriving (Show, Enum)
当我创建等差数列时,我必须在枚举实例和点号之前包含 space,例如
[Club .. Diamond]
为什么?
问题是,根据 Haskell's lexical rules,modid.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 规则,它说当有多种可能性匹配一个标记时,取匹配当前位置最长子串的那个。