#haskell
Вопрос:
В этом выражении x должно быть на 1 единицу больше, чем n. Однако результирующий список состоит в основном из отрицательных чисел.
f :: [Integer]
f = [x-n | x <- [1,2..], n <- [0,1..]]
Вывод из take 10 f
:
[1,0,-1,-2,-3,-4,-5,-6,-7,-8]
Я ожидал, что это будет список из 1, и я не уверен, почему это не так.
Спасибо.
Комментарии:
1. Я понимаю
[1,0,-1,-2,-3,-4,-5,-6,-7,-8]
, вы уверены, что результат действительно тот, который вы получаете?2. @Noughtmare Вы правы, я уже отредактировал вопрос. Спасибо.
3. @Мириам:
[0,1..]
это бесконечный список, содержащий0
,-1
,-2
,-3
,… Поэтому он никогда не будет использовать второй пунктx <- [1, 2 ..]
списка.4. Мне непонятно, почему вы ожидаете список из них. Можете ли вы объяснить, чего вы хотите достичь?
5. @WillemVanOnsem Я пытаюсь взять каждый элемент x, минус каждый элемент n. Возможно, я неправильно понимаю выражение?
Ответ №1:
В вашем определении для каждого значения x
каждое значение n
сопряжено с ним. Например, рассмотрим
g :: [Integer]
g = [ (x, n) | x <- [1,2..4], n <- [0,1..3]]
На выходе получается
[(1,0),(1,1),(1,2),(1,3),(2,0),(2,1),(2,2),(2,3),(3,0),(3,1),(3,2),(3,3),(4,0),(4,1),(4,2),(4,3)]
Если вы хотите, чтобы элементы x
и n
были соединены в пары по их соответствующим позициям, попробуйте zip
:
f1 = [x-n | (x, n) <- zip [1,2..] [0,1..]]
> take 10 f1
[1,1,1,1,1,1,1,1,1,1]
Ответ №2:
Код, который вы даете
f :: [Integer]
f = [x-n | x <- [1,2..], n <- [0,1..]]
является ли императив эквивалентным
for x in range(1, inf):
for n in range(0, inf):
return x - n
так ясно, x
это 1
сначала, а затем он петляет n
до бесконечности. Таким образом, вы получаете 1 - 0
, 1 - 1
1 - 2
, и т. Д…
Из вашего вопроса я предполагаю, что вы хотите сопоставлять элементы из каждого списка по одному вместо вложенного цикла. Следовательно, код должен быть
zipWith (-) [1..] [0..] -- this is equal to the infinite list [1,1,1,1,...]
Ответ №3:
Как упоминает @Willem Van Onsen в комментариях, ваше понимание сводится к вложенному циклу, где внешний цикл на x никогда не переходит к следующей итерации. То, что вы видите, таким образом (1 — n) для каждого значения n.
Что вам, кажется, нужно, так это соединить два списка вместе, а затем выполнить вычитание, вот так:
f = map (x -> (fst x) - snd x) $ zip [1,2..] [0,1..]
Это позволит взять элементы из каждого списка попарно и выполнить вычитание, чтобы получить ответ 1, как вы ожидаете.