То, что вы написали, содержит пару мелких ошибок:
[x | x <- [nums], x == even, x <= 50]
x <- [nums]
свяжет x
с каждым элементом списка [nums] :: [[Int]]
, который имеет один элемент, nums :: [Int]
. Предположительно, вы хотели x <- nums
, так что x :: Int
.
x == even
пытается сравнить x
, который имеет тип Int
, с функцией even
, которая имеет тип Integral a => a -> Bool
(или, немного упрощенно, Int -> Bool
). Вы не можете сравнивать значения разных типов на равенство и сравнивать функции; то, что вы хотите сделать, это вызов функция even
на x
с even x
.
С этими изменениями ваше выражение будет работать без ошибок:
[x | x <- nums, even x, x <= 50]
Теперь, что касается чтения значений из консоли, вы должны сделать это с main
, так как для этого требуется IO
:
main :: IO ()
main = do
putStrLn "Enter space-separated list of numbers."
line <- getLine
let nums = map read (words line) :: [Int]
print [x | x <- nums, even x, x <= 50]
При этом используется words
для разделения строки на пустом месте, map read
для преобразования каждой строки в результирующем списке в Int
и, наконец, ваше понимание списка для вычисления результата. Теперь ввод, такой как 10 25 30 45 50 60
, будет производить вывод, такой как [10,30,50]
.
Пара упражнений для улучшения вашего понимания:
Переместите запрос, анализ и усвоение списка в отдельные определения функций верхнего уровня с сигнатурами типов.
Что происходит, когда пользователь вводит неверный ввод, например 10, 20, foo
? Как вы могли справиться с этой ошибкой?