Tuple evaluation - haskell

I'm writing a function of the following type:
match :: [(String,a)] -> Maybe (String, a, a)
I want the function to traverse the list of tuples, and determine if there are any tuples in which the first element (a string) is the same. If so, I want to return a tuple containing that string, as well as the second element in each of those matching tuples. If there are no matching tuples, return "Nothing". If there is more than one matching, return the first one it finds.
For example:
match [("x", 3), ("y", 4), ("z", "5"), ("x", 6)] = ("x", 3, 6)
match [("x", 3), ("y", 4), ("z", "5")] = Nothing
I'm thinking:
match (x:xs) = if (fst x) = (fst xs) return (fst x, snd x, snd xs)
--if no matches, return Nothing
Thank you for any help!

What if there are three or four tuples with "x"? You can't have variable-length tuples. Maybe you want to return a list:
match :: [(String, a)] -> Maybe (String, [a])
What if there are several tuples that match? Do you want them all, or just the first? If you want them all then you should return a list of matches.
match :: [(String, a)] -> [(String, [a])]
If you think of it like this, then you can see that grouping all the "x" pairs together, and "y" pairs, and so on, would be a good start. You can do this by using
sortBy (comparing fst) xs
comparing takes a function and two values, applies the function to each, and compares the results. sortBy uses its first argument as a comparison function, so sortBy (comparing fst) sorts your list into order by the first element in each tuple.
Then you can use groupBy to collect the elements together.
Edit:
groupBy has the type
groupBy :: (a -> a -> Bool) -> [a] -> [[a]]
So you need to write a function equalFirst to give it as a parameter. So then
groupBy equalFirst $ sortBy (comparing fst) xs
will give you
[[("x", 3), ("x", 6)], [("y", 4)], [("z", 5)]]
Which is a list of lists. Each sub-list contains tuples with the same letter.
Now you can write a function which takes one of these sublists and converts it into the result you want. Then apply it to the list of lists using map.

Related

How to list all possible ways to pair up a list?

I'm new to Haskell and need to list all possible ways to pair up (even) lists of Ints.
E.g.
[1,2,3,4] -> [[(1,2),(3,4)], [(2,3),(1,4)], [(1,3),(2,4)], ...]
Generating all possible pairs is easy enough (shown below) but I can't work out how to return only ways to pair up the entire input list.
pairs :: [a] -> [[(a, a)]]
pairs l = [(x,y) | (x:ys) <- tails l, y <- ys]
I recommend writing a function that nondeterministically chooses an element, returning the rest of the values in the list as well. There are a few possible APIs; the one I suggest below is the most general-purpose one, and one I've used on many occasions for apparently unrelated tasks.
zippers :: [a] -> [([a], a, [a])]
Here's an example of what this function does:
> zippers "abcd"
[("", 'a', "bcd"), ("a", 'b', "cd"), ("ba", 'c', "d"), ("cba", 'd', "")]
Once you have that, you can simply repeatedly non-deterministically choose an element from the ever-shrinking list of available options, making a pair after every other choice.
We can make use of a helper function pick that returns a list of 2-tuples with as first element the item picked, and a second element a list of remaining elements:
pick :: [a] -> [(a, [a])]
pick [] = []
pick (x:xs) = (x, xs) : …
where the … part should make a call to pick with the tail of the list, and prepend each second item of the 2-tuples returned with x.
With this pick function we can then construct all combinations with:
pairs :: [a] -> [[(a, a)]]
pairs [] = [[]]
pairs (x:xs) = [(x,y):tl | (y, zs) <- pick xs, tl <- pairs zs]

How to update a certain tuple element within a list of tuples?

Haskell beginner here.
I have a list of tuples type (a, b) like so: [(1, "One"), (2, "2")], and a single pair (key, value).
I want to create a recursive function that accepts a pair and a list of tuples all type (a, b) and returns the list after replacing all values associated to the passed key with the passed value:
changeTup :: (Eq a) => (a,b) -> [(a,b)] -> [(a,b)]
Example output:
> changeTup (1, "Hello") [(1, "One"), (2, "Two")]
=> [(1, "Hello"), (2, "Two")]
I did some digging and it seems like the best way to do this is with map. I tried this but haven't gotten any good results.
This is my code:
changeTup :: (Eq a) => (a,b) -> [(a,b)] -> [(a,b)]
changeTup (y,z) [] = [(y,z)]
changeTup (y,z) (x:xs) = map replace
where replace (key, value)
| y == key = (key, z)
| otherwise = (key, value)
I'm not sure how to approach increments the list (x:xs) within map. I'm getting an expected type error.
The thing about the map function is that iterating over a list (or another vaguely list-shaped thing) is its entire job. In the code you have, you have a perfectly fine replace function, and you want to apply to the elements of the list (x : xs) - and doing that is as simple as map replace (x : xs)

Taking a list of tuples and returning a tuple

I am writing a recursive function in Haskell that takes a list of tuples as input and returns one tuple. The first part of the tuple that is being returned should be the number of tuples that were in the list, and the second part of the tuple returned should be all of the elements from every tuple in the list. To clear it up here is what an example run should look like:
gather [ (0, [true, true] ), (1, [true, false] ), (2, [false, true]) ]
returns (3, [true, true, true, false, false, true] )
I am fairly new to Haskell but here is my attempt of the recursive code:
gather [()] = [()]
gather n as = head as : gather n (take n as)
tupList :: [(a)] -> [(a)]
tupList n xs = map (\x -> gather n (take x xs)) [n..]
The compiler does not like this at all, any suggestions on what I can do to fix this? Thanks for your time!
First let me get you a working version (I hope this is not homework):
gather :: [(a,[b])] -> (Int, [b])
gather xs = (length xs, concatMap snd xs)
now to your version:
first you gave no signature but the two cases for gather already differ in the number of arguments (the first one would have type [()] -> [()], the second something like Int -> [a] -> [a] (what you really want is what I gave - or so I guess based on your example).
The next think is that I don't know what you are trying to do with gather - if you explain your thinking I will try to get you on track.
For what you need tupList I have no clue.
remark
I know that you wanted a recursive function - but this is only preferable IMO if this is homework ... so I am feeling not guilty of not giving you a recursive version ... if you want you can just rewrite the concatMap part (or length) using recursion.
based on your comment
I think you wanted to do the right think: split the problem into two parts: concatenating the lists and counting the items.
Counting the items is rather simple: either you use length or you redefine it:
length :: [a] -> Int
length [] = 0
length (_:tl) = 1 + length tl
The first problem should look something like this:
concat :: [[a]] -> [a]
concat [] = []
concat (xs:xss) = undefined
maybe you can try and fill this out yourself (it's most likely ok for you to use (++))
Having both you can just do as I did if you rewrite it into:
gather ts = (length ts, concat (map snd ts))
straight from GHCi : your example
λ> gather [(0, [True, True] ), (1, [True, False] ), (2, [False, True])]
(3,[True,True,True,False,False,True])
here's a recursive version. it performs only one pass along the input list. doing two independent passes often causes space leaks.
gather xs = g 0 xs
where
g c [] = (c, [])
g c ((_,ys):r) = (a, ys ++ b)
where
(a,b) = c `seq` g (c+1) r
seq causes the immediate calculation of a counter as we advance along the list. Without it the calculation of c+1 might be delayed unnecessarily.
This is guarded recursion, actually.

Haskell Invert Pair

Wondering if I could get some help writing this function. I am trying to create a function that inverts each "pair" in the list.
module Invert where
invert :: [(a,b)] -> [(b,a)]
invert [(a,b)] = [(b,a)]
When I enter invert [(3,1) (4,1) (5,1)]... it is supposed to give me [(1,3) (1,4) (1,5)... But it gives me...
*Invert> [(3,1) (4,1) (5,1)]
<interactive>:2:2:
The function `(3, 1)' is applied to two arguments,
but its type `(t0, t1)' has none
In the expression: (3, 1) (4, 1) (5, 1)
In the expression: [(3, 1) (4, 1) (5, 1)]
In an equation for `it': it = [(3, 1) (4, 1) (5, 1)]
Since lists are recursive data structures, you have to process a list recursively in order to swap all its elements, or use some higher order function that does the processing for you. If you define
invert [(a,b)] = [(b,a)]
it will only convert single-element lists, all other inputs will fail with an error!
Try to think about the input invert gets: It's either an empty list, or a non-empty lists. In the case of a non-empty list, you can swap the first element and convert the rest recursively.
(If you don't want to invert invert yourself, just use
invert = map swap
where swap is from Data.Tuple.)
Best way to solve this: split it into smaller problems, and either find library functions that solve those, or write your own. I always tell beginners that this is a superior exercise than trying to write a function like invert in just one part, because you should be learning the following three things:
How to split a problem into small, reusable pieces.
The standard library functions offered by the language.
How to use recursion to write small, reusable functions like the ones in the standard library.
In this case, we can split the problem into:
Inverting an individual tuple.
Applying a function to all elements of a list, and collecting the list of results.
The second one is just the common map function on lists, which comes with the standard library. You could try writing your own version of it; this sort of thing is always a good exercise for a beginner:
map :: (a -> b) -> [a] -> [b]
map f [] = ...
map f (x:xs) = ...
The first, as Petr points out, is the swap function from Data.Tuple. But we can write our own easily:
swap :: (a, b) -> (b, a)
swap (a, b) = (b, a)
And now, of course:
invert :: [(a, b)] -> [(b, a)]
invert = map swap
So you want to map a function over the list that's of type (a, b) -> (b, a). The function (,) has type b -> a -> (b,a). So if we flip it, we get a -> b -> (b, a). Now if we uncurry that, we get (a, b) -> (b, a):
invert = map (uncurry $ flip (,))
E.g.
> map (uncurry $ flip (,)) [(1, "a"), (2, "b")]
[("a",1),("b",2)]
As an aside, your patten matching doesn't match what you want. The definition
invert [(a,b)] = [(b,a)]
says "match a list with a single tuple in it". If you have a list with multiple tuples, the match will fail. Also, as Josh Lee pointed out, you need commas between tuples in your list.

Delete list elements by looking on another list

I have two lists. One list contains some random data and other list contains the index of first list which needs to be deleted.
For example, let us consider two lists:
let a = [3,4,5,6,6,7,8]
let b = [1,3]
Then, the resultant output should be [3,5,6,7,8]. The number 4 and 6 are deleted since they are on index positions 1 and 3 respectively.
I'm new to Haskell, so finding it difficult to find the solution.
Update: Following code makes it work
import Data.List
dele :: Eq a => [a] -> [Int] -> [a]
dele [] _ = []
dele x [] = x
dele x (y:ys) = dele (delete (x !! y) x) ys
I was just wondering, is there a way to solve it through map/fold way ?
deleteByIndex :: (Enum a, Eq a, Num a) => [a] -> [b] -> [b]
deleteByIndex r = map snd . filter (\(i, _) -> notElem i r) . zip [0..]
[0..] produces an infinite list [0, 1, 2, 3, ...]
zip constructs a list of pairs with the values of this list and your input list in the form [(0,x), (1, y), ...]
filter takes a function a -> Bool. The lambda checks if the index (first element of the pair) is in your input list r.
map snd returns the second element of each pair of the zip list.
zip,filter, map and notElem are documented here
Off the top of my head:
removeByIndex :: [Integer] -> [a] -> [a]
removeByIndex indices = map snd . filter notInIndices . zip [0..]
where notInIndices (i,_) = i `notElem` indices
An alternative answer using the lens library which has received considerable attention recently
import Control.Lens
>let a = [3,4,5,6,6,7,8]
>let b = [1,3]
>a^..elements (`notElem`b)
[3,5,6,7,8]
(^..) is jus the infix for of toListOf which can be used to traverse a structure and make a list out of its parts. The elements function just lets you choose which ones to include.
Other options are 'traverse' to traverse a traversables, 'both' to traverse a (,) and they compose together with (.) so traverse.both would traverse [(1,2), (3,4)] for example.
[(1,2), (3,4)]^..traverse.both
[1,2,3,4]

Resources