Понимание списка с несколькими процедурами - PullRequest
0 голосов
/ 08 мая 2018

Я действительно новичок в haskell и пытаюсь выучить основы, теперь я хотел попробовать
немного понимания списка.

Я хочу создать список (не заканчивающийся) с неровными числами из 0 to …, где number `mod` 13 == 3 и number `mod` 20 == 5.

Тогда я хочу использовать функцию take и взять первые 5 чисел этого списка
и покажи им.

Мой код был таким:

take 5 [x | x <- [0..], odd x == False, x > 0, x `mod` 13 == 3, x `mod` 20]

Теперь я получаю ошибки в haskell и не знаю, что делать с:

> <interactive>:14:19: error:  
    • No instance for (Num Bool) arising from the literal ‘0’  
    • In the expression: 0  
      In the expression: [0 .. ]  
      In a stmt of a list comprehension: x <- [0 .. ]  
<interactive>:14:25: error:  
    • No instance for (Integral Bool) arising from a use of ‘odd’  
    • In the first argument of ‘(==)’, namely ‘odd x’  
      In the expression: odd x == False  
      In a stmt of a list comprehension: odd x == False  

Кто-нибудь знает, как я могу сделать это правильно?

Ответы [ 3 ]

0 голосов
/ 08 мая 2018

Проблема в

x mod 20

в конце понимания. Вы не сравниваете его ни с чем, поэтому он не может отфильтровать ваш список.

0 голосов
/ 08 мая 2018

Ошибка из-за x мод 20. Это выражение возвращает тип Num и вам нужен Bool. Например, если вы хотите сравнить результат модуля с 0:

take 5 [x | x <- [0..], even x, x `mod` 13 == 3, x `mod` 20 == 0]
0 голосов
/ 08 мая 2018

Виновник в последней части:

take 5 [x | x <- [0..], odd x == False, x > 0, x `mod` 13 == 3, x `mod` 20]
--                                                              ^^^^^^^^^^

Здесь Haskell ожидает, что вы напишите фильтр, но x `mod` 20 - это , а не - фильтр: он делает не return a Bool, x `mod` 20 возвращает тот же тип номера, что и сам x.

Исходя из вашего вопроса, вы хотите, чтобы это было пять, поэтому можете решить его с помощью:

take 5 [x | x <- [0..], odd x == False, x > 0, x `mod` 13 == 3, x `mod` 20 == 5]
--                                                              ^^^^^^^^^^^^^^^

Но здесь есть и другие проблемы:

  1. вы написали "неровно", поэтому проверка odd x должна быть True;
  2. x > 0 всегда может быть True, поскольку мы ограничиваем итератор от x до [1..];
  3. мы можем объединить x <- [1..] и odd x в [1, 3..];

Это приводит к:

take 5 [x | x <- [1, 3..], x `mod` 13 == 3, x `mod` 20 == 5]

Тем не менее нам все равно не нужна вся эта проверка по модулю: мы можем сначала вычислить наименьшее общее кратное из 2 (нечетное ограничение), 20 и 13, что составляет 260, в результате мы знаем, что числа в результате принимают "прыжки", равные 260.

Мы также знаем, что первый результат равен 185, поэтомуэто может бытьзаписано:

take 5 [185, 445 ..]
...