August Flanagan
August Flanagan

Reputation: 896

Return a boolean value from a list comprehension

I'm brand new to haskell and am working through some tutorial problems for a functional programming course I am taking. There is one problem that I am completely stumped on.

Define a function that returns whether a given string contains all numerical values or not (i.e. "123" => True, "1a3" => False). The function must use a list comprehension.

It's this last part that is killing me. It's easy to write without a list comprehension. It's also easy to write a list comprehension with a predicate to ensure that you only put numerical chars into a new list.

isNum  =  [ x | x <- xs, x `elem` ['0'..'9'] ]

However I'm not sure how to then compare the new list to the original list to check for equality since this is the entire function definition.

Upvotes: 1

Views: 4600

Answers (8)

franza
franza

Reputation: 2317

You can use this partial function:

isNum :: [Char] -> Bool
isNum = foldl (\acc x -> acc && x `elem` ['0'..'9']) True

Example:

Prelude> isNum "111"
True
Prelude> isNum "111aaa"
False

Upvotes: 0

Satvik
Satvik

Reputation: 11208

isNum xs = null [ x | x <- xs, x notElem ['0'..'9'] ]

Just check the list is empty or not ..

Upvotes: 0

reader_1000
reader_1000

Reputation: 2501

Although there is an answer marked as correct, I think the complete implementation will be like this:

isNum xs = foldr (&&) True [x `elem`['0'..'9'] | x <- xs] -- or

isNum xs = foldl (&&) True [x `elem`['0'..'9'] | x <- xs] -- or

isNum xs = and [x `elem`['0'..'9'] | x <- xs] -- Thanks for the comment of hammar

isNum "123" -- returns True
isNum "1a3" -- returns False

Upvotes: 0

pat
pat

Reputation: 12749

I guess the homework requires a list comprehension, but the idiomatic way to do this would be:

import Data.Char
isNum = all isDigit

as a joke, if you want to think outside the box, you could throw in a list comprehension, but ignore it!

isNum =
    let unnecessaryListComprehension = [x | x <- [0..]]
    in all isDigit

or using a Monoid

import Data.Monoid
isNum xs = getAll $ mconcat [All $ isDigit x | x <- xs]

Upvotes: 1

user445408
user445408

Reputation:

If I were you, I'd just check that the list [x | x <- xs, not (elem x ['0'..'9'])] is empty.

Upvotes: 3

vivian
vivian

Reputation: 1434

Is this homework?

Since the list comprehension will only include characters that are numerals, if there are any non-numeric elements, the resulting list will be shorter.

Another approach is to put isNum xs = [ elem x ['0'..'9'] | x <- xs ]. Then you have a list of Boolean values telling you whether each character was a numeral. You can use a Prelude function to tell you whether all the values were True or not.

EDIT: more efficiently, there is also a Prelude function that can tell you whether any of the elements was False, indicating a non-numeric element.

Upvotes: 0

llayland
llayland

Reputation: 203

As small a hint as I can think of for the solution that first comes to my mind:

x elem ['0'..'9'] is useful for this, but not as a guard.

Upvotes: 1

rampion
rampion

Reputation: 89043

hint: use a list comprehension, not consist only of a list comprehension.

is there some list you can generate, and then run some further processing on to get the answer you need?

Upvotes: 3

Related Questions