Haskell: Почему дополнительное пространство необходимо для арифметической последовательности для пользовательского перечисления?

Поэтому для любых встроенных типов в Haskell я могу построить арифметическую последовательность, такую как эта (для Int или Integer и т.д.),

[1..5]

Но если я определяю тип перечисления типа:

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

когда я создаю арифметическую последовательность, я должен включать пробел перед экземпляром enum и точкой dot, например

[Club .. Diamond]

Зачем?

Ответ 1

Проблема в том, что, согласно лексическим правилам Haskell, modid.varsym является ссылкой на переменную в модуле. modid является последовательность из 1 или более заглавных идентификаторов, разделенных точками, а 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, в котором говорится, что когда есть несколько возможностей для соответствия токену, возьмите ту, которая соответствует самой длинной подстроке из текущей позиции.