Reputation: 119
I want to use list comprehension to print only true
listTo::(a->b)->[a]->[b]
listTo f list=[f(x)|x<-list,x==True]
isTrue::Int->Bool
isTrue n
|n>=5 =True
|n<5 =False
listTo isTrue[1,2,3,4,5,6,7]
But this doesn't work. Why is it?
Upvotes: 4
Views: 6676
Reputation: 71430
[f(x)|x<-list,x==True]
This says "give me a list of f x
1, where x
comes from list
and x
is equal to True
.
But for your case, you've passed list
as a list of numbers. And it looks like you want to only include those numbers for which f x
returns True
. So rather than comparing x
against True
and emitting f x
, you should be doing the opposite. Something more like:
[x | x <- list, f x == True]
But we can improve this a little further. ==
is a function which takes two arguments and returns True
if they're equal and False
if they're not. So f x == True
is going to return True
if f x
is True
, and False
if f x
is False
. Seems like a waste of effort; you could just write f x
!
[x | x <- list, f x]
So that's how you use a list comprehension to do this. But as postman noted, there is already a standard library function to do exactly this: filter
. That's what you would use if you were writing code to get things done, rather than to learn how things work.
1 Note that f(x)
is just parsed as f
applied to the parenthesised sub-expression (x)
. Putting parentheses around x
does nothing, so that's exactly equivalent to f x
. Haskell's syntax for function application is not C-like function(arg1, arg2, arg3)
, but rather function arg1 arg2
, where the arguments are simply written out after the function (separated by whitespace if necessary). Parentheses are used only for controlling precedence and forming tuples. If you start trying to call functions on multiple arguments by putting parentheses around the argument list you're going to run into even more errors.
Upvotes: 5
Reputation: 139840
In listTo
, list
has type [a]
. Therefore x
has type a
. But then you're comparing x == True
, which means that x
should have type Bool
- a contradiction.
If you change the type signature to listTo :: (Bool -> b) -> [Bool] -> [b]
, it compiles. However, you won't be able to use it with listTo isTrue [1,2,3,4,5,6,7]
as [1,2,3,4,5,6,7]
is obviously not of type [Bool]
.
It's not entirely clear to me what this code is supposed to be doing, but you should look into using map
or filter
.
Upvotes: 3
Reputation: 136
You should really consider using filter
, like this:
filter isTrue [1,2,3,4,5,6,7]
Upvotes: 5