I need to write a function to merge two lists. Exactly like '++' is working.
let x = merge [1,2,3] [3,3,4] -- should output [1,2,3,3,3,4]
How should it be done?
Edit: solution is
merge :: [a] -> [a] -> [a]
merge [] ys = ys
merge (x:xs) ys = x : (merge xs ys)
Maybe something like this.
merge :: (a -> a -> Bool) -> [a] -> [a] -> [a]
merge pred xs [] = xs
merge pred [] ys = ys
merge pred (x:xs) (y:ys) =
case pred x y of
True -> x: merge pred xs (y:ys)
False -> y: merge pred (x:xs) ys
(++) xs ys = merge (\x y -> compare x y == LT) xs ys
Or, if you just need to repeat the functionality of (++), you can look up it's definition with hoogle which eventually leads you to the source code
(++) [] ys = ys
(++) (x:xs) ys = x : xs ++ ys
Related
i've tried to create a Haskell function that is merging 2 lists into a single list, where even indices in the new list are from list 1 and the odd are from list 2. Fill with 0's if not the same size.
For example:
[1] [10,15,20] => [1,10,0,15,0,20]
[2,3] [4,5] => [2,4,3,5]
I've tried to create a couple of versions but with no luck.
How can I create such a thing?
There is a interleave function, that does something similar, however, not exactly that. It 'merges' lists until one of them ends.
So you can write that function by yourself:
merge :: [Int] -> [Int] -> [Int]
merge (x:xs) (y:ys) = x : y : merge xs ys
merge (x:xs) [] = x : 0 : merge xs []
merge [] (y:ys) = 0 : y : merge [] ys
merge _ _ = []
When we have some elements on both sides, we take both of them. When one of elements is absent, we take 0 instead of it. In all other cases (it is the merge [] [] case) we end up with our recursion and return an empty list.
We can also slightly generalize our function to support any number-like type:
merge :: Num a => [a] -> [a] -> [a]
merge (x:xs) (y:ys) = x : y : merge xs ys
merge (x:xs) [] = x : 0 : merge xs []
merge [] (y:ys) = 0 : y : merge [] ys
merge _ _ = []
Also, we can go further and use def from Data.Default package to get the default value for our type, so we can use this function with not only lists of numbers:
import Data.Default
merge :: Default a => [a] -> [a] -> [a]
merge (x:xs) (y:ys) = x : y : merge xs ys
merge (x:xs) [] = x : def : merge xs []
merge [] (y:ys) = def : y : merge [] ys
merge _ _ = []
Using the idea from this answer of mine, using the transpose :: [[a]] -> [[a]] function,
interweaveWith :: a -> [a] -> [a] -> [a]
interweaveWith def xs ys =
-- 0 [1] [10,15,20] => [1,10,0,15,0,20]
concat $
zipWith const
(transpose [ xs ++ repeat def, -- no limit, padded with def
ys ++ repeat def ])
(transpose [xs, ys]) -- as long as the longest
I have lists of lists and need to combine it with another list of lists.
Example inputs:
A: [[1,2],[3,4],[5,6],[7,8]]
B: [[1,2],[3,4],[5,6],[7,8]]
Example output:
[[1,2,1,2],[1,2,3,4],..,[7,8,5,6],[7,8,7,8]]
2 lists of lists with 4 lists inside both would return us a list of lists size 4*4 = 16
I've tried just recursively combine the lists, but i know it wouldn't work even if would go through.
mergeAll [[]] [[]] = [[]]
mergeAll [[]] b = b
mergeAll a [[]] = a
mergeAll xs ys = mergeAll (merge xs ys) (drop 1 ys)
merge :: [[a]] -> [[a]] -> [[a]]
merge [[]] [[]] = [[]]
merge xs [[]] = xs
merge [[]] ys = ys
merge (x:xs) (y:ys) = ((x++y):xs)
You can use a list comprehension:
[ xs ++ ys | xs <- listOfLists1, ys <- listOfLists2 ]
You may do like
Prelude> let doit = \as bs -> as >>= \a -> bs >>= \b -> pure (a ++ b)
Prelude> doit [[1,2],[3,4],[5,6],[7,8]] [[1,2],[3,4],[5,6],[7,8]]
[[1,2,1,2],[1,2,3,4],[1,2,5,6],[1,2,7,8],[3,4,1,2],[3,4,3,4],[3,4,5,6],[3,4,7,8],[5,6,1,2],[5,6,3,4],[5,6,5,6],[5,6,7,8],[7,8,1,2],[7,8,3,4],[7,8,5,6],[7,8,7,8]]
As Robin says in a comment, you can also do it like:
liftA2 (++)
I ask my self a question trying to understand why that is equivalent to:
[xs ++ ys | xs <- xss, ys <- yss]
merge :: [a] -> [a] -> [a]
merge xs [] = xs
merge [] ys = ys
merge (x:xs) (y:ys) = x : y : merge xs ys
maxOfTwoLists [x] [y] = maximum (merge [x] [y])
I am trying to combine the two lists then find the max value in the single list. It compiles but when i call maxOfTwoLists it gives me a non-exhaustive patterns error. My merge returns a single list just fine, and maximum takes a single list. So it feels like it should be working.
If you're looking to merge two lists, the builtin concat would help. It flattens a list, so we could do the following:
maxOfTwoLists :: (Ord a) => [a] -> [a] -> a
maxOfTwoLists xs ys = maximum $ concat [xs,ys]
In which, $ means to evaluate the result of the right side function before applying it to the left side function.
As #badcook notes the pattern match isn't quite right.
merge :: [a] -> [a] -> [a]
merge xs [] = xs
merge [] ys = ys
merge (x:xs) (y:ys) = x : y : merge xs ys
maxOfTwoLists :: (Ord a) => [a] -> [a] -> a
maxOfTwoLists [] ys = maximum ys
maxOfTwoLists xs [] = maximum xs
maxOfTwoLists xs ys = maximum (merge xs ys)
I'll guess you wrote the merge function as an exercise but you can also use ++ from Prelude to append one list to another.
maxOfTwoLists :: (Ord a) => [a] -> [a] -> a
maxOfTwoLists xs ys = maximum (xs ++ ys)
Output:
λ> maxOfTwoLists [1,2,3] [4,5,6]
6
λ> maxOfTwoLists [1,2,3] []
3
λ> maxOfTwoLists [] [1,2,3]
3
λ>
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"]
I'm trying to make an example function tail recursive.
Here is the original function:
let rec s xs ys =
match (xs, ys) with
|([],[]) -> []
|(xs, []) -> xs
|([], ys) -> ys
|(x::xs,y::ys) -> x::y::s xs ys
Below is my attempt to make it tail recursive:
let sC xs ys =
let rec sCTR xs ys acc =
match (xs, ys) with
|([],[]) -> acc
|(xs, []) -> acc#xs
|([], ys) -> acc#ys
|(x::xs,y::ys) -> sCTR xs ys acc#[x]#[y]
sCTR xs ys []
My issue is, however, that the order of the items are all wrong.
When I input the lists [1;2;3;] [7;8;] in the first function I get the result [1; 7; 2; 8; 3]
But when I input [1;2;3;] [7;8;] in the second function I get [3; 2; 8; 1; 7]
Why is the order wrong? I thought that list1#list2 would result in a new list with the order of list1 elements first and then list2 elements
You've just assumed the wrong precedence for #; what you've got is interpreted as
(sCTR xs ys acc)#[x]#[y]
but what you want is
sCTR xs ys (acc#[x]#[y])