I have a list of tuples, for example:
[(1,2), (3,4), (5,6)]
Now I have to write function which sum up the first an second element of each tuple and create a list of these values.
For the example above it should be:
[3, 7, 11]
This should be done with use of list comprehension. It's not allowed to use functions like map, filter and contact.
Any ideas how I could access the elements of the tuple in the list?
Try this:
[ x + y | (x,y) <- yourlist]
The trick is representing the two elements in a tuple from your input list as x and y and then dealing with them as needed.
Let's do it without list comprehensions, using functions from the Prelude:
map (uncurry (+)) [(1,2), (3,4), (5,6)]
-- Result: [3, 7, 11]
How does this work? Let's consider the types:
(+) :: Num a => a -> a -> a
uncurry :: (a -> b -> c) -> (a, b) -> c
map :: (a -> b) -> [a] -> [b]
As you may already know, in Haskell, the normal way of doing multi-argument functions is by **currying* them. The type of (+) reflects this: conceptually it takes one argument and produces a function that then takes the "second" argument to produce the final result.
uncurry takes such a curried two-argument function and adapts it to work on a pair. It's trivial to implement:
uncurry :: (a -> b -> c) -> (a, b) -> c
uncurry f (a, b) = f a b
Funnily enough, the uncurry function is curried, so its partial application uncurry (+) has type Num a => (a, a) -> a. This would then be a function that takes a pair of numbers and adds them.
And map simply applies a function to every element of a list, collecting the individual results into a list. Plug them all together and that's a solution.
Related
I am trying to generate all possibles combinations from two lists and then only return those that match the lambda function. So I currently have the following code:
func :: [a] -> [b] -> ((a, b) -> Bool) -> [(a, b)]
func xs ys f = filter f (tup)
where
tup = concat(map (\x -> map (\y -> (x,y))ys) xs)
Currently I am able to generate all the possible combinations, but the filtering won't work.
Error for the input : func [1,2,3] [4,5] (\ a b -> a+b > 6)
• Couldn't match expected type ‘Bool’ with actual type ‘(a, b) -> Bool’
• The lambda expression ‘\ a b -> a + b > 7’ has two value arguments, but its type ‘(a, b) -> Bool’ has only one
How can I solve this?
I tried to use map instead of filter, but that did not work as well.
Making a function with two arguments and making a function with a single 2-tuple argument use slightly different syntax:
\a b -> a+b > 6 -- two arguments
\(a, b) -> a+b > 6 -- one tuple argument
I built a list of this structure:
[(Interger, Double)]
The List was created by using a zip over a list of Integers and a list of Doubles of exactly the same size.
Now I want to filter the list for Doubles that are either <18.5 or >25. The problem I have is I can't access the Doubles to use them in the filter function.
It's probably easy but I'm a bloody noob in this language. I googled around a lot and read some other threads but I didn't find an answer.
I got:
filter (<18.5) listexpression
So what I'm struggling with is that listexpression. It's easy if it's a list of single values. I could filter before zipping but then I can't connect the data from the filtered list to the other unfiltered List anymore.
Edit: I forgot to mention. It's a worksheet. We were asked to build filter and map functions ourselves and are not allowed to use any additions to the basic Haskell. Meaning no imports are allowed.
You can do something like this:
Prelude> filter (\p -> (snd p) < 18.5 || (snd p) > 25) [(1, 2.3), (1, 20.0)]
[(1,2.3)]
The lambda function passed to filter, namely
(\p -> (snd p) < 18.5 || (snd p) > 25)
says that for every p, the second element of p must be less than 18.5 or over 25.
Alternatively, you could write it like this
Prelude> filter (\(_, f) -> f < 18.5 || f > 25) [(1, 2.3), (1, 20.0)]
[(1,2.3)]
Here the function says that for any pair whose first value doesn't matter and the second one is f, f must be less than 18.5 or over 25.
Glad to see Ami Tavory's answer solved your problem.
But under that answer, you commented:
I tried accessing it with a combination of (!!) but that didn't work.
With the insight of a teaching assistant [:D], I guess you confused list with tuple in Haskell.
zip returns a list of tuple, whereas (!!) take a list as (the first) argument (hence (!!1) take a single list argument), so (!!1) can't be applied to elements of the list returned by zip, which are of type tuple.
Prelude> :t zip
zip :: [a] -> [b] -> [(a, b)]
Prelude> :t (!!)
(!!) :: [a] -> Int -> a
Prelude> :t (!!1)
(!!1) :: [a] -> a
And you've known that fst and snd are applied to tuple.
Prelude> :t fst
fst :: (a, b) -> a
Prelude> :t snd
snd :: (a, b) -> b
A compact version using point free style would be
filter ((>18.5).snd) listexpression
This uses the function composition operator ., which reads as: First apply the snd function to a tuple from the list to extract the 2nd value, then apply the comparison to 18.5 to this value.
Just for a variety and some additional information which won't bite...
In Haskell the list type is an instance of Monad class. So a list operation like filter can simply be implemented by a monadic bind operator.
*Main> [(1,2.3),(3,21.2),(5,17.1),(4,24.4)] >>= \t -> if snd t < 25 && snd t > 18.5 then [t] else []
[(3,21.2),(4,24.4)]
Monad is all about handling the contained data in a sequential manner. In the list monad the contained data is the value within the list itself. So the bind operator can be very handy to access to contained values (tuples) of the monadic value (the list of tuples) in a sequential manner.
(>>=) :: Monad m => m a -> (a -> m b) -> m b
The type signature of the monadic bind operator states that it takes a monad type value m a as the first argument (the list of tuples here) and a function as the second argument which takes a pure value and returns a monadic value (takes a tuple and returns a tuple in a list or an empty list in this case).
\t -> if snd t < 25 && snd t > 18.5 then [t] else []
It's critical to understand how and why the list items are applied one by one to the provided function. An entire list is one monadic value and the contained values those accessed by the bind operator are passed to the provided a -> m b (take a pure value and return monadic value) type function. So all of the list items those applied to this function become a monadic value ([t] if condition satisfies or [] if it fails), are then concatenated by the bind operator to form one monadic return value (in this case a list of tuples those satisfy the condition which is implemented in the lambda function).
This monadic operation can also be implemented with the do notation
do
t <- [(1,2.3),(3,21.2),(5,17.1),(4,24.4)]
if snd t < 25 && snd t > 18.5 then return t else []
[(3,21.2),(4,24.4)]
Of course this terribly resembles the list comprehensions which is in fact a syntactical sugar to the monadic list operations. So lets implement it for a final time by using the list comprehensions.
*Main> [t | t <- [(1,2.3),(3,21.2),(5,17.1),(4,24.4)], snd t < 25 && snd t > 18.5]
[(3,21.2),(4,24.4)]
I know about the length function, but if I have a list such as [(1,2),(2,3),(3,4)] and try to use length it does not work. I tried to concatenate but that doesn't help. Any idea how?
While the sensible solution to your immediate problem is (2 *) . length, as 9000 pointed out, it is worth dwelling a bit on why length [(1,2),(2,3),(3,4)] doesn't do what you expect. A Haskell list contains an arbitrary number of elements of the same type. A Haskell pair, however, has exactly two elements of possibly different types, which is something quite different and which is not implicitly converted into a list (see this question for further discussion of that point). However, nothing stops us from writing a conversion function ourselves:
pairToList :: (a, a) -> [a]
pairToList (x, y) = [x, y]
Note that the argument of pairToList is of type (a, a); that is, the function only accepts pairs with both elements having the same type.
Given pairToList, we can convert the pairs in your list...
GHCi> map pairToList [(1,2),(2,3),(3,4)]
[[1,2],[2,3],[3,4]]
... and then proceed as you planned originally:
GHCi> (length . concat . map pairToList) [(1,2),(2,3),(3,4)]
6
The concatMap function combines map and concat into a single pass...
GHCi> :t concatMap
concatMap :: Foldable t => (a -> [b]) -> t a -> [b]
... and so your function becomes simply:
GHCi> (length . concatMap pairToList) [(1,2),(2,3),(3,4)]
6
length [(1,2),(2,3),(3,4)] gives you 3 because there are precisely three elements in the list where the elements are tuples, each consisting of two integers. use this function to get all the "elements"
tupleLength :: [(Int, Int)] -> Int
tupleLength = (*2) . length
Given two lists, [a, b] and [c, d], I'd like to get the following result:
[(a,c), (a,d), (b,c), (b,d)]
How can I do this in Haskell? Is there a built-in function for this, or should I implement one myself?
[ (x,y) | x<-[a,b], y<-[c,d] ]
This doesn't really require any further explanation, does it?
Applicative style all the way!
λ> :m + Control.Applicative
λ> (,) <$> ['a','b'] <*> ['c','d']
[('a','c'),('a','d'),('b','c'),('b','d')]
(I've eschewed any String syntactic sugar above, in order to stay close to your example.)
For information, (,) is special syntax for a function that takes two arguments and makes a pair out of them:
λ> :t (,)
(,) :: a -> b -> (a, b)
Edit: As noted by leftaroundabout in his comment, you can also use liftA2:
λ> :m + Control.Applicative
λ> let combine = liftA2 (,)
λ> combine "ab" "cd"
[('a','c'),('a','d'),('b','c'),('b','d')]
How can you do this in an imperative pseudocode?
for each element x in [a,b]:
for each element y in [c,d]:
produce (x,y)
In Haskell, this is written as
outerProduct xs ys =
do
x <- xs -- for each x drawn from xs:
y <- ys -- for each y drawn from ys:
return (x,y) -- produce the (x,y) pair
(following comments by leftaroundabout) this is of course extremely close to how liftM2 monadic combinator is defined, so in fact
outerProduct = liftM2 (,)
which is the same as liftA2 (,), and its various re-writes in terms of list comprehensions, concatMap function, >>=, <$> and <*> operators.
Conceptually though this is the stuff of the Applicative – which would be better named as Pairing, – because this pairing up of the elements of two "containers" ⁄ "carriers" ⁄ whatever is exactly what Applicative Functor is about. It just so happens that Haskell's do notation works for monads, and not (yet) for applicatives.
In some sense compile-time nested loops are Applicative ⁄ Pairing functors; Monads add the ability to create nested loops on the fly, depending on the values produced by an "outer" enumeration.
The most inuitive would be using list comprehension, other aproaches include using applicative functors:
(,) <$> [1,2,3] <*> [4,5,6]
So what does this do?
Remember that (,) :: a -> b -> (a, b) Takes two arguments and returns a tuple.
<$> is acutally fmap, (<$>) :: Functor f => (a -> b) -> f a -> f b
It takes a function and lift it. In this case it takes (,) and lift it to work on list. So let x = (,) <$> [1,2] would generate x :: [b -> (Integer, b)] which is the the list of functions that takes b and returns tuple with one fixed argument (Integer,b). Finally we apply it using <*> to generate all the combinations.
use List Comprehension:
s = [a,b]
s' = [c,d]
all_combinations = [(x,y) | x <- s, y <- s']
So I want to put in two parameters into this function, a list and the position of the item that I want to print.
listNumber [1,2,3,4,5,6] 2
>> 3
I have tried this problem by doing this
numberList :: (List a) => a -> a -> a
numberList a b = [x | x <- a !! n, n <- b]
I don't know where my mistake is.
I think this is an interesting way of going about it.
If we ignore the type signature for the moment and look at the function:
numberList a b = [x | x <- a !! n, n <- b]
we see that n is called in the first condition of the list-comprehension:
x <- a !! n
but n is only defined after that, in the second condition:
n <- b
This leads to an error: Not in scope: `n'
So the first thing to do might be to switch the first and second conditions:
numberList a b = [x | n <- b, x <- a !! n]
Now asking GHCi about the type, we get:
Prelude> :t numberList
numberList :: [[t]] -> [Int] -> [t]
GHC expects parameter a to be a list of lists and parameter b to be a list of ints. This is because n is drawn from b and anything on the right side of <- in a list comprehension must be a list. Since n is used as a parameter for !!, GHC assumes that n is an int and b is a list of ints.
Now GHC assumes that x is also coming from some kind of list. So we know that GHC assumes a !! n is a list. But since by definition, a !! n is the element of list a at position n, we see why GHC assumes a is a list of lists -- because GHC assumes the element of list a at position n is the list from which x is drawn.
Here's a working example:
Prelude> numberList [[1,2,3,4,5,6]] [0]
[1,2,3,4,5,6]
Here GHC indeed shows us the element of list a at position 0, which is the list [1..6]. Unfortunately, this does not allow us to conveniently get at the positions inside the list, as we would like. An alternate way to still use a list comprehension may be to define a new list 'c' that contains the element we are after (a !! n) and draw x from this new list, like so:
Prelude> let numberList a b = [x | n <- b, let c = [a !! n], x <- c]
Prelude> numberList [1,2,3,4,5,6,3] [2]
[3]
It seems a bit convoluted, though, since we can simply use !! to get the element of a at position b directly:
Prelude> let numberList a b = a !! b
Prelude> numberList [1,2,3,4,5,6] 2
3
So I want to put in two parameters into this function, a list and the position of the item that I want to print.
>>> listNumber [1,2,3,4,5,6] 2
3
Okay. Step one: you have a really messed up type signature.
numberList :: (List a) => a -> a -> a
This should not be ignored. Starting with a good type signature is an essential skill for mastering good programming technique in Haskell and similar languages.
First, you want a function with two inputs.
numberList :: a -> b -> c
Next, you want the first input to be "a list." We don't know what this list contains, so we'll just use a type parameter a. The way to write "a list of a" is [a].
numberList :: [a] -> b -> c
You want the second input to be "the position." This will probably be an Int.
numberList :: [a] -> Int -> c
Finally, you want the result to be an element of the list. So it will therefore have the same type a.
numberList :: [a] -> Int -> a
I have no idea where you got that (List a) => part of the type signature, but it's totally bogus, unless you are using some custom library that you're not telling us about. This is quite possible if you are taking a university course on Haskell.
We have a type signature, and it might be handy to know if this has already been implemented for us. Stop! Hoogle time. Enter the type signature [a] -> Int -> a into http://haskell.org/hoogle . It turns out that you are trying to implement !!.