Reputation: 429
I have some problem with list comprehension, if the input is a list.
In these all III excercises it's not allowed to use: map
, filter
and concat
!!!
Requirements:
A funktion f1
gets a list xs
of tripels (a, b, cs)
where
a
and b
are of type Int
c
is of type [Int]
The function should generate a list of pairs (a · b, b + c)
, for all c in cs AND in the generated list should appear just those pairs in which the 1st element is bigger than the 2nd one - (a · b) > b + c
.
Example:
f1 [(10,20,[1,10,100]), (4,5,[5,15,25])]
should return the following list:
[(200,21),(200,30),(200,120),(20,10)]
My attempts:
f1 :: Int -> Int -> [Int] -> [(Int, Int)]
f1 a b cs = [(a*b, b+c)| c<-cs, (a*b)>(b+c)]
It works fine, however not for lists as input.
So I tried several ways, but unfortunately not the right one :-(
f1 :: [(Int, Int, [Int])] -> [(Int, Int)]
1st approach:
f1 xs = [((xs !! 0)*(xs !! 1), (xs !! 1)+c)| c<-(xs !! 2), ((xs !! 0)*(xs !! 1))>((xs !! 1)+c)]
2nd approach:
f1 let (a, b, cs) = xs = [(a*b, b+c)| c<-cs, (a*b)>(b+c)]
3rd approach:
f1 (a b cs) = [(a*b, b+c)| c<-cs, (a*b)>(b+c)]
All three don't work!
Solution by dave4420:
f1 :: [(Int, Int, [Int])] -> [(Int, Int)]
f1 xs = [ (a*b, b+c) | (a, b, cs) <- xs, c <- cs, (a*b)>(b+c) ]
Requirements:
A function g1 gets a list of pairs of same type and generate a plain list out of it.
Example:
g1 [(1,2),(3,4),(5,6)] returns [1,2,3,4,5,6]
My Attempt:
g1 :: [(Int, Int)] -> [Int]
g1 xs = [a,b | (a,b)<-xs]
I get a compiling error for this because a,b in the output of list comprehension does not have the correct syntax.
However I can return a or b or e.g. a+b:
g1 xs = [a | (a,b)<-xs]
or
g1 xs = [a+b | (a,b)<-xs]
Could you please help me out of this too?
Thanks once again
Part III is coming...
Upvotes: 0
Views: 837
Reputation: 47052
f1 :: [(Int, Int, [Int])] -> [(Int, Int)]
f1 xs = [ {-TODO-} | (a, b, cs) <- xs, c <- cs, {-TODO-} ]
I have left a couple of {-TODO-}s for you to fill in.
Part II.
If you had to write
g1' :: [[Int]] -> [Int]
how would you do that? Can you then modify g1'
into the g1
you desire?
Upvotes: 3
Reputation: 8136
You're 90% of the way there.
Remember that in GHCI you use let
before a definition,
but inside regular source code, you don't.
So let's see what you have so far.
λ> let f1 (a,b,cs) = [(a*b, b+c)| c<-cs, (a*b)>(b+c)]
Notice that I added commas in your tuple. Let's find out the type of f1
.
λ> :t f1
f1 :: (Num t, Ord t) => (t, t, [t]) -> [(t, t)]
For now, you can ignore the (Num t, Ord t) =>
part.
This is a function that takes a tuple containing an element, another
element, and a list of elements.
So we can't pass it the entire list of tuples,
only a single tuple.
λ> f1 (10,20,[1,10,100])
[(200,21),(200,30),(200,120)]
λ> f1 (4,5,[5,15,25])
[(20,10)]
That's the first part of the result you want.
λ> f1 (4,5,[5,15,25])
[(20,10)]
And that's the second part. So now you need another function that takes input that looks like this:
[(10,20,[1,10,100]), (4,5,[5,15,25])]
I.e., we want a function that takes a list of tuples.
Building on f1
, we can write something like this:
λ> let f2 xs = [f1 x | x <- xs]
λ> f2 [(10,20,[1,10,100]), (4,5,[5,15,25])]
[[(200,21),(200,30),(200,120)],[(20,10)]]
Notice that the result is a list of lists, and we just want a plain list.
Since you're not allowed to use concat
, take a look at how groovy or Daniel Fisher approached the problem.
Two different methods, both good.
Upvotes: 1
Reputation: 183888
You have come close. Using your
f1 :: Int -> Int -> [Int] -> [(Int, Int)]
f1 a b cs = [(a*b, b+c)| c<-cs, (a*b)>(b+c)]
you first need to rewrite that to take a triple (Int, Int, [Int])
. That's a trivial change,
f1_a :: (Int, Int, [Int]) -> [(Int, Int)]
f1_a (a,b,cs) = [(a*b, b+c) | c <- cs, a*b > b+c]
Now, you need to apply that function to each element of the input list of triples. That would be map f1_a xs
if you could use map
, but since you mustn't, write it as a list comprehension
f2 :: [(Int, Int, [Int])] -> [[(Int, Int)]]
f2 xs = [f1_a x | x <- xs]
But that has one level of lists too much, you want a flat list, so you need to concat
the list of lists. You are also not supposed to use concat
, so you need to write that as a list comprehension.
Now, what does concat
do?
For each of the lists in the argument, for each element in that list, put that element in the result, so
concat' xss = [x | xs <- xss, x <- xs]
Now apply that to f2
.
Upvotes: 1