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
Related
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)]
All I'm trying to do is sum a list of lists. Example of what I want to do:
Input: [[1,2,3],[2,5],[6,7]]
Output: [6,7,13]
The amount of lists inside the outer list can vary, and the amount of integers in each inner list can vary. I've tried a multitude of things, and this is the last one I tried but it doesn't work:
sumSubsets [[x]] = map sum [[x]]
Also, I wanted a base case of sumSubsets [] = [[]] but that causes errors as well. Any help would be appreciated.
You could use
sumSubsets x = map sum x
or even
sumSubsets = map sum
Your previous code,
sumSubsets [[x]] = map sum [[x]]
First performs a pattern match using [[x]] which matches a list containing a single element, which is itself a list containing a single element. Therefore it would work correctly on [[3]]
>> sumSubsets [[3]]
[3]
but not on [[1,2,3]] or [[1],[2]].
I think your problem stems primarily from mixing up types and values, which can happen easily to the beginner, in particular on lists. The whole confusion probably comes from the fact that in Haskell, [] is used as a data constructor as well as a type constructor.
For example, [Int] means "a list of Ints" (a type), but [1] means "the list that contains one element, namely the number 1" (a value -- meaning, the whole list is the value). Both things together:
xs :: [Int]
xs = [1]
When you write polymorphic functions, you abstract from something like the Int. For example, if you want to get the first element of a list, you can define a function that does that for any kind of list -- may they be lists of integers or lists of characters or even lists of lists:
firstElement :: [a] -> a
firstElement (x:xs) = x
[a] means "a list with elements of type a" (a type), and the a alone means "something of type a". firstElement is a function from a list with elements of type a to something of type a. a is a type variable. Since you're not saying what a should be, the function works for all kinds of lists:
*Main> firstElement [1,2,3]
1
*Main> firstElement ['a','b']
'a'
*Main> firstElement [[1,2],[3,4]]
[1,2]
When you wrote [[x]] you were perhaps thinking of the type of the first argument of the function, which would be a list of lists of elements of some type x (x is a type variable). You can still use that, but you have to put it into the type signature of your function (the line that contains the double colon):
sumSubsets :: Num a => [[a]] -> [a]
sumSubsets xs = map sum xs
I've used a here instead of x, since it's more commonly done, but you could use x, too. Unfortunately, the whole thing gets a bit complicated with the Num a which describes additional requirements on the type a (that it belongs to the numbers, since for other things, sum is not defined). To simplify matters, you could write:
sumSubsetsInts :: [[Int]] -> [Int]
sumSubsetsInts xs = map sum xs
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.
How can I get the index of the element I am at in haskell when I am using map ?
For example I have this list l = "a+bc?|(de)*fg|h" and I want to know the exact index of the element I am at when I use the map or scanl function.
Amending Nikita Volkov's answer, you can use a function such as:
-- variant of map that passes each element's index as a second argument to f
mapInd :: (a -> Int -> b) -> [a] -> [b]
mapInd f l = zipWith f l [0..]
First of all, if you need an index when processing a list it is a certain sign that you're implementing a suboptimal algorithm, because list is not an index-based structure like array. If you need to deal with indexes you better consider using a vector instead.
Concerning your actual question, you can pair the items of your list with incrementing ints with the following code and then map over the result:
Prelude> zip [0..] "a+bc?|(de)*fg|h" :: [(Int, Char)]
[(0,'a'),(1,'+'),(2,'b'),(3,'c'),(4,'?'),(5,'|'),(6,'('),(7,'d'),(8,'e'),(9,')'),(10,'*'),(11,'f'),(12,'g'),(13,'|'),(14,'h')]
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 !!.