Haskell - почему это понимание списка возвращает бесконечный список?

Jan 15 2021
[3 * x | x <- [1 ..], 3 * x < 20]

Я действительно не понимаю, почему это дает

[3,6,9,12,15,18

И не находит конца

Ответы

14 chi Jan 15 2021 at 23:37

Семантика

[3 * x | x <- [1 ..], 3 * x < 20]

состоит в том, чтобы опробовать все элементы [1..]и оставить те, которые удовлетворяют условию фильтра 3*x<20.

Человек может видеть, что после первого, xкоторое фальсифицирует условие, нет смысла пробовать все большие значения, но Haskell все равно попробует их и застрянет в своего рода бесконечном цикле.

Это потому, что в общем случае условие может снова стать истинным, например

[3 * x | x <- [1 ..], 3 * x < 20 || x == 1000000 ]

В общем - то неразрешимой обнаружить ли нет больше решений, поэтому Haskell, как и любой другой язык программирования, не может выбрать , чтобы остановить после последнего решения.

Если вы хотите, чтобы список останавливался после первого значения, которое не удовлетворяет условию фильтрации, используйте takeWhile:

takeWhile (< 20) [3 * x | x <- [1 ..]]