reverse zip 2 lists (without using zip or reverse) - list

I want to write a function that takes two lists as arguments and creates a list with a pair from each list consecutively, but in reverse.
for example:
reversezipLists [1, 2, 3] ['a', 'b', 'c']
would produce [('c', 3), ('b', 2), ('a', 1)].
Here is my attempt:
reversezipLists :: [a] -> [b] -> [(b,a)]
reversezipLists [] [] = []
reversezipLists [] ys = []
reversezipLists xs [] = []
reversezipLists (x:xs) (y:ys) = (y,x) : reversezipLists xs ys
the problem is the output of my code is: [('a',1),('b',2),('c',3)]. How can I reverse it?

Use an accumulator:
reversezipLists :: [a] -> [b] -> [(b, a)]
reversezipLists = go [] where
go acc [] _ = acc
go acc _ [] = acc
go acc (h1:t1) (h2:t2) = go ((h2, h1) : acc) t1 t2
Bonus points: the function is tail recursive. The basic idea is that we append new pairs to the acc during the left-to-right traverse through the lists. The stackish nature of Haskell lists makes the result reversed. Note that it will truncate longer list.
If you want to throw an error when the lists' lengths don't match, you can play a bit with patterns:
reversezipLists :: [a] -> [b] -> [(b, a)]
reversezipLists = go [] where
go acc [] [] = acc
go acc (h1:t1) (h2:t2) = go ((h2, h1) : acc) t1 t2
go _ _ _ = error "lists' sizes don't match"

r (x:xs) (y:ys) = (r xs ys) ++ [(y,x)]
r [] [] = []
r [1, 2, 3] ['a', 'b', 'c'] = [('c',3),('b',2),('a',1)]
it works only on lists of the same length

Related

Haskell - separate a list of pairs in two lists using fold

So, I am given a list containing tuples and I need to break it down into two lists, the first list containing the elements with odd index and the second list containing the elements with even index, must be done using fold, here is my attempt:
breakList :: [(Integer, Integer)] -> [[(Integer, Integer)]]
breakList [] = [[], []]
breakList xxs#(x:xs) = foldl (\ acc y -> if length (acc !! 0) < length (acc !! 1) then y : (acc !! 0) else y : (acc !! 1) ) [[], []] xxs
Error I am getting:
Couldn't match type '(Integer, Integer)'
with '[(Integer, Integer)]'
Expected type: [[(Integer, Integer)]]
when hovering over y : (acc !! 1) and y : (acc !! 0)
Example:
Input:
ex1 = [ (2, 2), (1, 3), (2, 3), (2, 4), (3, 5), (0, 2), (2, 1), (1, 4)
, (2, 0), (1, 2), (3, 1), (1, 0)]
Output
breakList ex1
== ( [(2,2),(2,3),(3,5),(2,1),(2,0),(3,1)] , [(1,3),(2,4),(0,2),(1,4),(1,2),(1,0)])
The standard trick here, as hinted at by Willem in the comments, which I first saw few years back on SO in an (F# or Ocaml) answer by [user:Ed'ka], is
evenodds :: [a] -> ([a], [a])
evenodds xs = foldr g ([],[]) xs
where
g x ~(as,bs) = (bs,x:as)
or
oddevens :: [a] -> ([a], [a])
oddevens xs = foldr g ([],[]) xs
where
g x ~(bs,as) = (x:as,bs)
What are odd positions from here, are even positions from the position one notch further on the list.
The tilde ~ introduces a lazy pattern so that the function is properly lazy in its operations.
Note that you want to split a list into two lists of a pair, so the return type should be
([(Integer, Integer)], [(Integer, Integer)])
not
[[(Integer, Integer)]]
and access the element of pair, you can use fst and snd instead of through index, and finally, use foldl will return the resulted list in reversed order, it can be fixed use foldr instead. The correction look like:
breakList :: [(Integer, Integer)]->([(Integer, Integer)], [(Integer, Integer)])
breakList xxs = foldr (\y acc-> if length (fst acc) < length (snd acc)
then (y:(fst acc), snd acc)
else (fst acc, y:(snd acc)) ) ([], []) xxs

Combining three lists into a list of 3-tuples in Haskell

I am trying to write a function that takes three lists as arguments and creates one list with a triple from each list consecutively.
The example I was given is this: zip3Lists [1, 2, 3] [4, 5, 6] ['a', 'b', 'c'] would produce [(1, 4, 'a'), (2, 5, 'b'), (3, 6, 'c')].
What I have so far is this:
zipThree [] [] [] = []
zipThree [] [] [x] = [x]
zipThree [] [x] [] = [x]
zipThree [x] [] [] = [x]
zipThree (x:xs) (y:ys) (z:zs) = (x, y, z) : zipThree xs ys zs
and it is giving me this error:
haskell1.hs:32:33: error:
• Occurs check: cannot construct the infinite type: c ~ (c, c, c)
Expected type: [c]
Actual type: [(c, c, c)]
• In the expression: (x, y, z) : zipThree xs ys zs
In an equation for ‘zipThree’:
zipThree (x : xs) (y : ys) (z : zs) = (x, y, z) : zipThree xs ys zs
• Relevant bindings include
zs :: [c] (bound at haskell1.hs:32:27)
z :: c (bound at haskell1.hs:32:25)
ys :: [c] (bound at haskell1.hs:32:20)
y :: c (bound at haskell1.hs:32:18)
xs :: [c] (bound at haskell1.hs:32:13)
x :: c (bound at haskell1.hs:32:11)
(Some bindings suppressed; use -fmax-relevant-binds=N or -fno-max-relevant-binds)
First of all let's add a type signature. From the question it seems as if the following type signature is appropriate:
zipThree :: [a] -> [b] -> [c] -> [(a, b, c)]
This takes 3 lists (containing possibly different types of objects) and then produces a list of triples.
You handle the empty list case fine:
zipThree [] [] [] = []
Then the problem occurs. As stated in the comments you have cases for the lists having different lengths but that give a different type of output.
I'll annotate the types next to each line so you can see:
zipThree [] [] [x] = [x] :: [c]
zipThree [] [x] [] = [x] :: [b]
zipThree [x] [] [] = [x] :: [a]
These don't fit with the other two cases that have type [(a, b, c)].
You mentioned in the comments that you will just presume the lengths are the same size therefore just removing these cases is sufficient. This gives:
zipThree [] [] [] = []
zipThree (x:xs) (y:ys) (z:zs) = (x, y, z) : zipThree xs ys zs
Which provides the correct output ([(1, 4, 'a'), (2, 5, 'b'), (3, 6, 'c')]) for the input you gave ([1, 2, 3] [4, 5, 6] ['a', 'b', 'c']).
This function of course will fail on inputs where the lists are of different lengths. One way to stop a straight up error and allow you to handle the issue would be to wrap the result in a Maybe.
First we need to change the type to:
zipThree :: [a] -> [b] -> [c] -> Maybe [(a, b, c)]
The Maybe data type can either be a value wrapped in Just so Just a or Nothing.
For the empty list we want to give just the empty list:
zipThree [] [] [] = Just [].
Naturally you might think that the next case should be:
zipThree (x:xs) (y:ys) (z:zs) = Just $ (x, y, z) : zipThree xs ys zs.
But this doesn't work. Don't forget zipThree xs ys zs now has type Maybe [(a, b, c)] whereas (x, y, z) has type (a, b, c) so we can't add it to the list.
What we need to do is check the result of zipThree xs ys zs if it failed at some point during the recursion then it will be Nothing so we just want to pass that Nothing along again. If it succeeded and gave us Just as then we want to add our (x, y, z) to that list. We can check which case is relevant using case of:
zipThree (x:xs) (y:ys) (z:zs) = case zipThree xs ys zs of
Nothing -> Nothing
Just as -> Just $ (x, y, z) : as
We will know our lists aren't the same length if at some point during the recursion some lists are empty and others aren't. This doesn't match either pattern we have at the moment [] [] [] or (x:xs) (y:ys) (z:zs) so we need one final catch all case to give us that Nothing and prevent the error:
zipThree _ _ _ = Nothing
This gives a final definition of:
zipThree :: [a] -> [b] -> [c] -> Maybe [(a, b, c)]
zipThree [] [] [] = Just []
zipThree (x:xs) (y:ys) (z:zs) = case zipThree xs ys zs of
Nothing -> Nothing
Just as -> Just $ (x, y, z) : as
zipThree _ _ _ = Nothing
The results for the examples are:
zipThree [1, 2, 3] [4, 5, 6] ['a', 'b', 'c', 'd'] = Nothing
and
zipThree [1, 2, 3] [4, 5, 6] ['a', 'b', 'c'] = Just [(1, 4, 'a'), (2, 5, 'b'), (3, 6, 'c')].
Hope this helps, feel free to ask for clarification :)
EDIT: As suggested in the comments the following definitions would stop short in the case the lists are different lengths:
zipThree :: [a] -> [b] -> [c] -> [(a, b, c)]
zipThree (x:xs) (y:ys) (z:zs) = (x, y, z) : zipThree xs ys zs
zipThree _ _ _ = []
zipThree :: [a] -> [b] -> [c] -> Maybe [(a, b, c)]
zipThree (x:xs) (y:ys) (z:zs) = case zipThree xs ys zs of
Nothing -> Just [(x, y, z)] -- Change is here
Just as -> Just $ (x, y, z) : as
zipThree _ _ _ = Nothing
P.S. Thanks to the guy who added the missing Just in an edit.
There is this ZipList type defined in Control.Applicative module which is in fact exactly thought for this job.
ZipList type is derived from the List type like
newtype ZipList a = ZipList { getZipList :: [a] }
deriving ( Show, Eq, Ord, Read, Functor, Foldable
, Generic, Generic1)
Unlike normal Lists it's Applicative instance does not work on combinations but one to one on corresponding elements like zipping. Hence the name ZipList. This is the Applicative instance of ZipList
instance Applicative ZipList where
pure x = ZipList (repeat x)
liftA2 f (ZipList xs) (ZipList ys) = ZipList (zipWith f xs ys)
The advantage of zipList is we chain up indefinitely many lists to zip with. So when zipWith7 is not sufficient you may still carry on with a ZipList. So here is the code;
import Control.Applicative
zip'mAll :: [Int] -> [Int] -> String -> [(Int,Int,Char)]
zip'mAll xs ys cs = getZipList $ (,,) <$> ZipList xs <*> ZipList ys <*> ZipList cs
*Main> zip'mAll [1,2,3] [4,5,6] "abc"
[(1,4,'a'),(2,5,'b'),(3,6,'c')]
Firstly, we need a type signature, as stated by James Burton, who lists a suitable one also:
zipThree :: [a] -> [b] -> [c] -> [(a, b, c)]
Essentially, this type signature says that, given three lists of any type a, b or c, a list of three-value tuples whose type is (a, b, c) shall be produced.
If we disregard the need to handle invalid cases (empty lists, variable-length lists), we next need to implement a valid case which produces the correct tuple from the lists given. Your statement
zipThree (x:xs) (y:ys) (z:zs) = (x, y, z) : zipThree xs ys zs
is valid. Therefore, thus far we have:
zipThree :: [a] -> [b] -> [c] -> [(a, b, c)]
zipThree (x:xs) (y:ys) (z:zs) = (x, y, z) : zipThree xs ys zs
The problem occurs when you introduce the cases for your invalid lists:
zipThree [] [] [x] = [x]
zipThree [] [x] [] = [x]
zipThree [x] [] [] = [x]
When one of these cases is matched, the type attempting to be bound is invalid due to being of type [x], where type (x, y, z) is expected.
You could exhaustively attempt to match base cases before recursively accessing the function again. However, you could also simply declare the case
zipThree _ _ _ = []
after, which will end the recursion with invalid input.
Putting this altogether, we are left with:
zipThree :: [a] -> [b] -> [c] -> [(a, b, c)]
zipThree (x:xs) (y:ys) (z:zs) = (x, y, z) : zipThree xs ys zs
zipThree _ _ _ = []
What's good about this implementation is that the recursion ends when any list is empty, thus stopping short for uneven lists, e.g.
zipThree [1, 2, 3] [4, 5, 6] [7, 8]
would produce
[(1, 4, 7), (2, 5, 8)]
Good luck!

How to insert a list in a list in all possible ways?

I am trying to enumerate all the possible merges of two lists.
In example inserting "bb" into "aaa" would look like
["bbaaa", "babaa", "baaba", "baaab", "abbaa", "ababa", "abaab", "aabba", "aabab", "aaabb"]
What I currently did is this
import Data.List
insert'' :: Char -> String -> [(String, String)] -> String
insert'' _ _ ([]) = []
insert'' h b ((x, y):xs) =
(x ++ [h] ++ (insert' (b, y))) ++ (insert'' h b xs)
insert' :: (String, String) -> String
insert' ([], ys) = ys
insert' (xs, ys) =
insert'' h b lists
where
h = head xs
b = tail xs
lists = zip (tails ys) (inits ys)
This returns for ("aaa", "bb")
"bbaaababaaabaababbaababaababbabababb"
a concatenated string, I tried making it a list of strings, but I just cannot wrap my head around this function. I always seems to get infinite type construction.
How could I rewrite the function, so it would return a list of strings?
An other implementation idea as in Daniel Wagners first post is to choose in each step a element from one of the lists and prepending it to the results generated by the function called with only the remaining parts of the list:
interleave :: [a] -> [a] -> [[a]]
interleave xs [] = [xs]
interleave [] ys = [ys]
interleave xs#(x : xs') ys#(y : ys') =
map (x :) (interleave xs' ys) ++ map (y :) (interleave xs ys')
For your intial example this produces:
ghci> interleave "bb" "aaa"
["bbaaa","babaa","baaba","baaab","abbaa","ababa","abaab","aabba","aabab","aaabb"]
Here is one implementation idea: for each element in the first list, we will choose (nondeterministically) a position in the second list to insert it, then recurse. For this to work, we first need a way to nondeterministically choose a position; thus:
choose :: [a] -> [([a], [a])]
choose = go [] where
go before xs = (before, xs) : case xs of
[] -> []
x:xs -> go (x:before) xs
For example:
> choose "abcd"
[("","abcd"),("a","bcd"),("ba","cd"),("cba","d"),("dcba","")]
Now we can use this tool to do the insertion:
insert :: [a] -> [a] -> [[a]]
insert [] ys = [ys]
insert (x:xs) ys = do
(before, after) <- choose ys
rest <- insert xs (reverse after)
return (before ++ [x] ++ rest)
In ghci:
> insert "ab" "cde"
["abcde","aebcd","adebc","acdeb","cabde","caebd","cadeb","dcabe","dcaeb","edcab"]
In this answer, I will give the minimal change needed to fix the code you already have (without completely rewriting your code). The first change needed is to update your type signatures to return lists of strings:
insert'' :: Char -> String -> [(String, String)] -> [String]
insert' :: (String, String) -> [String]
Now your compiler will complain that the first clause of insert' is returning a String instead of a [String], which is easily fixed:
insert' ([], ys) = [ys]
...and that the second clause of insert'' is trying to append a String to a [String] when running [h] ++ insert' (b, y). This one takes some thinking to figure out what you really meant; but my conclusion is that instead of x ++ [h] ++ insert' (b, y), you really want to run \t -> x ++ [h] ++ t for each element in insert' (b, y). Thus:
insert'' h b ((x, y):xs) =
(map (\t -> x ++ [h] ++ t) (insert' (b, y))) ++ (insert'' h b xs)
The complete final code is:
import Data.List
insert'' :: Char -> String -> [(String, String)] -> [String]
insert'' _ _ ([]) = []
insert'' h b ((x, y):xs) =
(map (\t -> x ++ [h] ++ t) (insert' (b, y))) ++ (insert'' h b xs)
insert' :: (String, String) -> [String]
insert' ([], ys) = [ys]
insert' (xs, ys) =
insert'' h b lists
where
h = head xs
b = tail xs
lists = zip (tails ys) (inits ys)
Now ghci will happily produce good answers:
> insert' ("aaa", "bb")
["bbaaa","babaa","baaba","baaab","abbaa","ababa","abaab","aabba","aabab","aaabb"]

haskell, is number in one list is within the range of a second list?

What is the best way to find out if a number in a list is within the range of a second list, using a Maybe data type?
What I have so far:
getElems :: [Int] -> [a] -> [Maybe a]
getElems [xs] ys
| head(tail[(xs)]) > head(tail[(ys)]) = [Nothing]
| otherwise = [Just xs]
It needs to return those elements that correspond to the positions specified. Depending on if a position is greater than the list size it returns Nothing, else Just value.
For example:
getElems [2,4] [1..10] ) [Just 3,Just 5]
getElems [2,4] [1..4] ) [Just 3,Nothing]
You can write an getElementByIndex which does that for a single list:
getElementByIndex :: Int -> [a] -> Maybe a
getElementByIndex n [] = Nothing
getElementByIndex n (x:xs) = if (n == 0)
then Just x
else getElementByIndex (n - 1) xs
And then just map it to get an answer:
getElems :: [Int] -> [a] -> [Maybe a]
getElems xs ys = map (\x -> getElementByIndex x ys) xs
Demo in ghci:
λ> getElems [2,4] [1..10]
[Just 3,Just 5]
λ> getElems [2,4] [1..4]
[Just 3,Nothing]

Creating tuples variations from a list - Haskell

I am a relative haskell newbie and am trying to create a list of tuples with an equation I named splits that arises from a single list originally, like this:
splits [1..4] --> [ ([1],[2,3,4]), ([1,2],[3,4]), ([1,2,3],[4]) ]
or
splits "xyz" --> [ ("x","yz"), ("xy","z") ]
Creating a list of tuples that take 1, then 2, then 3 elements, etc. I figured out I should probably use the take/drop functions, but this is what I have so far and I'm running into a lot of type declaration errors... Any ideas?
splits :: (Num a) => [a] -> [([a], [a])]
splits [] = error "shortList"
splits [x]
| length [x] <= 1 = error "shortList"
| otherwise = splits' [x] 1
where splits' [x] n = [(take n [x], drop n [x])] + splits' [x] (n+1)
The Haskell-y approach is to use the inits and tails functions from Data.List:
inits [1,2,3,4] = [ [], [1], [1,2], [1,2,3], [1,2,3,4] ]
tails [1,2,3,4] = [ [1,2,3,4], [2,3,4], [3,4], [4], [] ]
We then just zip these two lists together and drop the first pair:
splits xs = tail $ zip (inits xs) (tails xs)
or equivalently, drop the first element of each of the constituent lists first:
= zip (tail (inits xs)) (tail (tails xs))
splits [] = []
splits [_] = []
splits (x:xs) = ([x], xs) : map (\(ys, zs) -> (x:ys, zs)) (splits xs)
You have several mistakes.
You don't need to have Num a class for a.
use [] or [x] as pattern, but not a variable, use xs instead.
Use ++ instead of + for concatenating lists.
In our case use (:) to add list to value instead of ++.
Add stop for recursion, like additional variable maxn to splits'
splits :: [a] -> [([a], [a])]
splits [] = error "shortList"
splits xs
| lxs <= 1 = error "shortList"
| otherwise = splits' xs 1 lxs
where
lxs = length xs
splits' xs n maxn
| n > maxn = []
| otherwise = (take n xs, drop n xs) : splits' xs (n+1) maxn
There is a built in function that kind of does a part of what you want:
splitAt :: Int -> [a] -> ([a], [a])
which does what it looks like it would do:
> splitAt 2 [1..4]
([1,2],[3,4])
Using this function, you can just define splits like this:
splits xs = map (flip splitAt xs) [1..length xs - 1]