Я читаю Learn You A Haskell for Great Good . Его примеры [2,2..20]
и [3, 6..20]
работают нормально, но я получил три странных результата:
[17, 1..171]
возвращает пустой список. [17, 17..171111]
повторяет число 17
, пока я не прерву GHCi. Существует странная разница между дублем 54 [171, 234 ..]
и дублем 54 [171, 244 ..]
:
ghci> дублем 54 [171 , 234 ..]
[171,234,297,360,423,486,549,612,675,738,801,864,927,990,1053,1116,1179,1242,1305,1368,1431,1494,1557,1620,1683,1746,1809,1872,1935,1998,2061,2124,2187 , 2250,2313,2376,2439,2502,2565,2628,2691,2754,2817,2880,2943,3006,3069,3132,3195,3258,3321,3384,3447,3510]
{{ 1}} ghci> взять 54 [171, 244 ..]
[171,244,317,390,463,536,609,682,755,828,901,974,1047,1120,1193,1266,1339,1412,1485,1558,1631,1704,1777,1850,1923,1996, 2069,2142,2215,2288,2361,2434,2507,2580,2653,2726,2799,2872,2945,3018,3091,3164,3237,3310,3383,3456,3529,3602,3675,3748,3821, 3894,3967,4040]
Почему?
У вас есть смысл немного отклоняться от диапазона. Синтаксис диапазона Хаскеля - одна из четырех вещей: [first..]
, [first,second..]
, [first..last]
, [first,second..last]
. Примеры из Learn You A Haskell :
ghci> [2,4..20]
[2,4,6,8,10,12,14,16,18,20]
ghci> [3,6..20]
[3,6,9,12,15,18]
Обратите внимание, что в первом случае список отсчитывается вдвое, а во втором - список считает по три. Это потому, что разница между первым и вторым элементами составляет два и три, соответственно. В своем синтаксисе вы пытаетесь написать [first,step..last]
, чтобы получить список [first,first+step,first+2*step,...,last]
; однако размер шага такого диапазона на самом деле является разницей между первыми двумя числами. Без второго элемента размер шага всегда один; и без последнего элемента список продолжается вечно (или пока не будет достигнут максимальный / минимальный элемент типа).
Итак, давайте посмотрим на ваши три примера:
[17,1..171] == []
. Поскольку вы указываете 17,1
, Хаскелл видит, что первые два элемента вашего списка должны быть семнадцать и один, так что вы должны считать -16
. В этом случае Haskell хочет остановиться, как только элементы будут на меньше , чем последний элемент, - но они начинаются таким образом, и поэтому элементы не создаются. Чтобы сосчитать на единицу, вы хотите [17,18..171]
(первые два элемента вашего списка - 17 и 18) или просто [17..171]
.
[17, 17..171111] == repeat 17
. Это весело. Поскольку первые два элемента вашего списка оба 17
, Haskell определяет, что вы должны считать до нуля, и он будет рад продолжать считать до тех пор, пока результат не превысит 171111
. Конечно, при подсчете нуля этого никогда не произойдет, и вы получите бесконечный список семнадцати подростков. Чтобы подсчитать до семнадцати, вы хотите [17,34..171111]
или [17,17+17..171111]
, если считаете, что это понятнее.
take 54 [171,234..]
против take 54 [171,244..]
. Я не уверен, какое поведение вы ожидаете здесь, но то, что они делают, является таким же, как указано выше: первое возвращает список из пятидесяти четырех целых чисел, начиная с 171
и считая с 234 - 171 = 63
; вторая возвращает список из 54 целых чисел, начиная с 171
и считая с 244 - 171 = 73
. Каждый список идет бесконечно далеко (или, по крайней мере, до maxBound
, если списки конечны Ints
, а не произвольно большие Integers
), и поэтому вы просто запрашиваете первые пятьдесят четыре элемента.
Для некоторых из более мелких деталей о том, что означает синтаксис диапазона (он переведен в функции в классе типа Enum
), включая немного удивительное поведение в диапазонах чисел с плавающей точкой, hammar имеет хороший ответ на другой вопрос .
Меня также смутил этот урок: в уроке используется слово шаг, которое не объясняется, и, на мой взгляд, это не то, что я считаю шагом. Затем он показывает пример, который легко может быть неверно истолкован. поскольку [2,4..20]
выглядит так, как будто это шаг 2, начинающийся с 4.
Подсказка есть в выводе:
ghci> [2,4..20]
[2,4,6,8,10,12,14,16,18,20]
, если вы посмотрите внимательно (чего я не сделал) , Это означает, что начиная с 2, следующим является 4, с неявным шагом отныне (4 - 2), переходите к выходным числам с шагом от 2 до максимум 20.
"ghci>" [1,6..20]
[1,6,11,16]
Примечание 20 не выходной сигнал 16 + 5 больше 20