svineet
svineet

Reputation: 1889

Using or in list comprehension

I'm trying to take out every number between 1 to 10 that is divisible by either 5 or 3
Here is my code till now -

giveList = 
[ x
 | x <- [1..10] ,
 (x `mod` 5 == 0) or (x `mod` 3 == 0)
]

And then I load the function in ghci. But it's giving me a error -

> [1 of 1] Compiling Main             ( problem1.hs, interpreted )

problem1.hs:4:10:
    The function `x `mod` 5 == 0' is applied to two arguments,
    but its type `Bool' has none
    In the expression: (x `mod` 5 == 0) or (x `mod` 3 == 0)
    In a stmt of a list comprehension:
      (x `mod` 5 == 0) or (x `mod` 3 == 0)
    In the expression:
      [x | x <- [1 .. 10], (x `mod` 5 == 0) or (x `mod` 3 == 0)]
Failed, modules loaded: none.

My question is -

I'm new to functional programming, please help me.

Upvotes: 4

Views: 490

Answers (4)

Landei
Landei

Reputation: 54584

In fact, I might be not so bad to use or here:

[x | x <- [1..10], or $ map ((==0).(x `mod`)) [3,5]]

... or probably more readable ...

[x | x <- [1..10], any (==0) $ map (x `mod`) [3,5]]

The down side is that it might look a little bit scary, but on the up side you can easily test for more divisors that way.

Upvotes: 0

Benjamin Hodgson
Benjamin Hodgson

Reputation: 44634

or has a type signature of or :: [Bool] -> Bool. It takes a list of Boolean values, and returns True if any one of them is True, or False otherwise.

The function you're looking for is || :: Bool -> Bool -> Bool. It takes two Boolean values, and returns True if either of them is True, or False otherwise.

[x | x <- [1..10], x `mod` 5 == 0 || x `mod` 3 == 0]

Upvotes: 8

Gricha
Gricha

Reputation: 1032

You can do list comprehension like that:

[x | x <- [1..10], ((x `mod` 3) == 0) || ((x `mod` 5) == 0)]

or function works on lists

Upvotes: 2

Daniel Fischer
Daniel Fischer

Reputation: 183968

You can use or in list comprehensions, but

Prelude> :t or
or :: [Bool] -> Bool

that is not the one you need at that place, it's a function that checks whether any element in the list is True. There you need

(||) :: Bool -> Bool -> Bool

And if you want to use a function with a name consisting of letters infix, you need to enclose it in backticks, like you did with mod, but since or takes only one argument, you cannot apply that function infix.

A correct version of your list would be

giveList = [ x | x <- [1 .. 10], x `mod` 5 == 0 || x `mod` 3 == 0]

Upvotes: 13

Related Questions