user10656336
user10656336

Reputation:

How to combine filter and mapping in Haskell

I'm making some exercises with haskell. My Task is to create a list of squares of even numbers without 0 from the list [0..10].

I already made it with the list comprehension in Haskell (Take a look in the code block below.) but now my task is to implement this with the function map and 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

I implemented the map and filter function ( I know it is superfluous but it practices me ) and I have a square function. Now the problem is to combine the map with the filter and I also get an error message at p = (\x -> mod x 3 == 0 && x/=0).

My error message is <interactive>:4:1: error: Variable not in scope : p :: Integer -> t

Upvotes: 3

Views: 9230

Answers (1)

Will Ness
Will Ness

Reputation: 71065

You already have everything you need here. You wrote

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

But this means you could also write

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

So now we do have the two functions, foo f ys for mapping a function f over a list ys, and bar p xs for testing each element of xs by a predicate p and filtering out all that fail to pass that test (i.e. all xs such that p x == False). And, it turns out, we already had their definitions!

All we needed to extract them from our raw code was abstraction.

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

Upvotes: 4

Related Questions