Не думаю, что понимаю, что здесь происходит. Не должно ли все, что справа от |
быть ограничением?
Нет, в правой части вы видите выражение, которое представляет собой разделенный запятыми (,
) список «частей», и каждая часть представляет собой одно из следующего дерева:
- «генератор» формы
somevar <- somelist
;
- a
let
оператор , который является выражением, которое может использоваться, например, для представления переменной, которая хранит подрезультат; и
- выражения типа boolean, действующие как filter .
Так что это не своего рода " программирование с ограничениями ", где можно просто перечислить некоторые ограничения и надеяться, что Хаскелл это выяснит (на самом деле, лично в этом заключается разница между "языком программирования" и «язык спецификации»: на языке программирования вы «управляете» тем, как данные передаются на языке спецификации, который обрабатывается системой, которая читает ваши спецификации)
По сути, итератор можно сравнить с циклом «foreach» во многих императивных языках программирования. Выражение «let» можно рассматривать как представление временной переменной (но учтите, что в Haskell вы не присваиваете переменную, вы объявляете их, поэтому вы не можете переназначать значения). Фильтр можно рассматривать как оператор if
.
Таким образом, понимание списка было бы эквивалентно чему-то в Python вроде:
for y in range(100, 1000):
for z in range(y, 1000):
x = y * z
s = str(x)
if x == x[::-1]:
yield x
Таким образом, мы сначала итерируем по двум диапазонам вложенным способом, затем объявляем x
умножением y
и z
, при let s = show x
мы в основном конвертируем число (например, 15129
) к его строковому аналогу (например, «15129»). Наконец, мы используем s == reverse s
, чтобы перевернуть строку и проверить, равна ли она исходной строке.
Обратите внимание, что существуют более эффективные способы проверки палиндромов, особенно для умножения двух чисел.