Диапазоны в Haskell (GHCi)

Я читаю Learn You A Haskell for Great Good . Его примеры [2,2..20] и [3, 6..20] работают нормально, но я получил три странных результата:

  1. Подсчет на 17 единиц от единицы до 171: [17, 1..171] возвращает пустой список.
  2. Сосчитайте по 17 от семнадцати до 1711111: [17, 17..171111] повторяет число 17 , пока я не прерву GHCi.
  3. Существует странная разница между дублем 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] 
     

Почему?

31
задан Alasdair 31 October 2011 в 22:30
поделиться

2 ответа

У вас есть смысл немного отклоняться от диапазона. Синтаксис диапазона Хаскеля - одна из четырех вещей: [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].

  • [1 134]

    [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 имеет хороший ответ на другой вопрос .

50
ответ дан 27 November 2019 в 22:00
поделиться

Меня также смутил этот урок: в уроке используется слово шаг, которое не объясняется, и, на мой взгляд, это не то, что я считаю шагом. Затем он показывает пример, который легко может быть неверно истолкован. поскольку [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

2
ответ дан 27 November 2019 в 22:00
поделиться
Другие вопросы по тегам:

Похожие вопросы: