Reputation: 896
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
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
Reputation: 11208
isNum xs = null [ x | x <- xs, x notElem
['0'..'9'] ]
Just check the list is empty or not ..
Upvotes: 0
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
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
Reputation:
If I were you, I'd just check that the list [x | x <- xs, not (elem x ['0'..'9'])]
is empty.
Upvotes: 3
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
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
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