开发者

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" => Tr开发者_StackOverflow中文版ue, "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.


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?


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


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.


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]


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.


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


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

Just check the list is empty or not ..


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
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜