Как совместить фильтр и отображение в Haskell - PullRequest
0 голосов
/ 14 апреля 2019

Я делаю упражнения с Haskell. Моя задача - создать список квадратов четных чисел без 0 из списка [0..10].

Я уже сделал это с пониманием списка в Haskell (посмотрите на блок кода ниже), но теперь моя задача - реализовать это с помощью функций map и filter.

List comprehension in Haskell:
[x^2 | x <- [0..10], mod x 2==0, x/=0]


f = (\x -> (x^2))
p = (\x -> mod x 2 == 0 && x/=0)

map1 :: (a->b) -> [a] -> [b]
map1 f [] = []
map1 f (x:xs) = f x : map1 f xs

filter1 :: (a -> Bool) -> [a] -> [a]
filter1 p [] = []
filter1 p (x:xs)
 | p x = x:filter p xs
 | otherwise = filter1 p xs

Я реализовал функции map и filter (я знаю, что это излишне, но это практикует меня), и у меня есть функция квадрата. Теперь проблема в том, чтобы объединить map с filter, и я также получаю сообщение error на p = (\x -> mod x 3 == 0 && x/=0).

Мое сообщение об ошибке <interactive>:4:1: error: Variable not in scope : p :: Integer -> t

1 Ответ

1 голос
/ 14 апреля 2019

У вас уже есть все, что вам нужно здесь. Вы написали

let res = [ x^2 | x <- [0..10], <b>mod x 2==0</b>, <b>x/=0</b> ]

Но это означает, что вы также можете написать

let res = [ y^2 | y <- [ x | x <- [0..10] 
                           , <b>(mod x 2==0 && x/=0)</b> ] ]
==
let res = [ y^2 | y <- [ x | x <- [0..10], <b>test x</b> ] ]
   where
   <b>test x</b> = (mod x 2==0 && x/=0)
==
let res = [ y^2 | y <- baz <b>[0..10]</b> ]
   where
   baz <b>xs</b> = [ x | x <- <b>xs</b>, test x ]
   test x = (mod x 2==0 && x/=0)
==
let res = [ sqr y | y <- bar <b>test</b> [0..10] ]
   where
   sqr y = y^2
   bar <b>p</b> xs = [ x | x <- xs, <b>p</b> x ]
   test x = (mod x 2==0 && x/=0)
==
let res = quux <b>( bar test [0..10] )</b>
   where
   quux <b>ys</b> = [ sqr y | y <- <b>ys</b> ]
   sqr y = y^2
   bar p xs = [ x | x <- xs, p x ]
   test x = (mod x 2==0 && x/=0)
==
let res = foo <b>sqr</b> ( bar test [0..10] )
   where
   foo <b>f</b> ys = [ <b>f</b> y | y <- ys ]
   sqr y = y^2
   bar p xs = [ x | x <- xs, p x ]
   test x = (mod x 2==0 && x/=0)

Итак, теперь у нас есть две функции: foo f xs для отображения функции f над списком xs и bar p xs для проверки каждого элемента xs с помощью предиката p и фильтрации все, что не прошло этот тест (то есть все x s, что p x == False). И, оказывается, у нас уже были их определения!

Все, что нам нужно для извлечения их из нашего необработанного кода, было абстракция .

let res = <b>map</b> sqr ( <b>filter</b> test [0..10] )
   where
   sqr y = y^2
   test x = (mod x 2==0 && x/=0)
...