Haskell:为什么用户定义的枚举算术序列需要额外的空间?

Mic*_*Mac 19 haskell user-defined-types

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

[1..5]
Run Code Online (Sandbox Code Playgroud)

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

data Suit = Club | Diamond | Heart | Spade deriving (Show, Enum) 
Run Code Online (Sandbox Code Playgroud)

当我创建一个算术序列时,我必须在枚举实例和点点之前包含空格,例如

[Club .. Diamond]
Run Code Online (Sandbox Code Playgroud)

为什么?

sep*_*p2k 23

问题在于,根据Haskell的词法规则,modid.varsym是对模块中变量的引用.A modid是由点分隔的1个或多个大写标识符的序列,a varsym是符号名称.Club是有效的modid并且.是有效的varsym(请注意,Prelude中的操作符甚至可以作为该名称访问Prelude..).因此X..被视为.模块中命名的变量的限定名称X.

因此Club..Diamond被标记为"限定变量名,构造函数名称",而不是"构造函数名称,dotdot,构造函数名称" 1.当它尝试解析限定变量名时,它会失败,因为实际上没有一个名为的模块Club.

[1..5]因为1不是有效的模块名称,也没有其他方式1..1.形成有效的令牌,所以不会出现此问题.请注意,与某些语言不同,1.不允许将其作为较短的写入方式1.0.如果是,你会遇到类似的问题,因为1..5现在会被标记为"数字,点,数字".但事实并非如此,所以问题不会发生.


1 "合格的变量名称"胜过"构造函数名称,dotdot",因为最大的munch规则表示当有多种匹配令牌的可能性时,请从当前位置获取匹配最长子串的那个.