How to remove duplicate items in nested list? - list

I have a Haskel function called flatten that works as such:
flatten :: [[a]] -> [a]
flatten [] = []
flatten ([]:vs) = flatten vs
flatten ((x:xs):vs) = x:flatten (xs:vs)
It takes a list of lists and combines it into one list. How can I make another function called flatten2set that works exactly like flatten (or calls flatten), but removes all duplicates, if any? I want to try and do this without tools like nub.
An example would be:
flatten2set [[1],[5,1,4],[9,1,3],[2,5]] --> [1,5,4,9,3,2]
I have attempted to implement a nub function:
nub:: Eq a => [a] -> [a]
nub (x:xs) = x : filter (/=x) (myNub xs)
nub [] = []
And when I have tried to use it like this:
flatten2set :: [[a]] -> [a]
flatten2set[x] = (myNub . flatten) [x]
I receive this error:
testing.hs:20:18: error:
• No instance for (Eq a) arising from a use of ‘myNub’
Possible fix:
add (Eq a) to the context of
the type signature for:
flatten2set :: forall a. [[a]] -> [a]
• In the first argument of ‘(.)’, namely ‘myNub’
In the expression: myNub . flatten
In the expression: (myNub . flatten) [x]
Any help would be appreciated!

You have an excellent implementation of myNub
myNub :: Eq a => [a] -> [a]
myNub (x:xs) = x : filter (/=x) (myNub xs)
myNub [] = []
Then you try to call it
flatten2set :: [[a]] -> [a]
flatten2set = myNub . flatten
But you've declared that flatten2set works for any a. The compiler is simply pointing out that that cannot be. What if we tried to call flatten2set with a list of lists of functions? It won't work because myNub requires Eq and functions are not comparable. Since we call a function that requires Eq a, we too must require Eq a.
flatten2set :: Eq a => [[a]] -> [a]
flatten2set = myNub . flatten
I took the liberty of removing the [x], which had no purpose. If you really want to have an argument, you just name the argument. There's no need to pattern match on it.
flatten2set :: Eq a => [[a]] -> [a]
flatten2set x = (myNub . flatten) x
Using [x] is an assertion that, in this case, the list will contain exactly one element, and we want flatten2set to work on lists containing any number of elements.

Related

Sum corresponding elements of two lists, with the extra elements of the longer list added at the end

I'm trying to add two lists together and keep the extra elements that are unused and add those into the new list e.g.
addLists [1,2,3] [1,3,5,7,9] = [2,5,8,7,9]
I have this so far:
addLists :: Num a => [a] -> [a] -> [a]
addLists xs ys = zipWith (+) xs ys
but unsure of how to get the extra elements into the new list.
and the next step is changing this to a higher order function that takes the combining function
as an argument:
longZip :: (a -> a -> a) -> [a] -> [a] -> [a]
zipWith :: (a -> b -> c) -> [a] -> [b] -> [c] is implemented as [src]:
zipWith :: (a->b->c) -> [a]->[b]->[c]
zipWith f = go
where
go [] _ = []
go _ [] = []
go (x:xs) (y:ys) = f x y : go xs ys
It thus uses explicit recursion where go will check if the two lists are non-empty and in that case yield f x y, otherwise it stops and returns an empty list [].
You can implement a variant of zipWith which will continue, even if one of the lists is empty. THis will look like:
zipLongest :: (a -> a -> a) -> [a] -> [a] -> [a]
zipLongest f = go
where go [] ys = …
go xs [] = …
go (x:xs) (y:ys) = f x y : go xs ys
where you still need to fill in ….
You can do it with higher order functions as simple as
import Data.List (transpose)
addLists :: Num a => [a] -> [a] -> [a]
addLists xs ys = map sum . transpose $ [xs, ys]
because the length of transpose[xs, ys, ...] is the length of the longest list in its argument list, and sum :: (Foldable t, Num a) => t a -> a is already defined to sum the elements of a list (since lists are Foldable).
transpose is used here as a kind of a zip (but cutting on the longest instead of the shortest list), with [] being a default element for the lists addition ++, like 0 is a default element for the numbers addition +:
cutLongest [xs, ys] $
zipWith (++) (map pure xs ++ repeat []) (map pure ys ++ repeat [])
See also:
Zip with default value instead of dropping values?
You're looking for the semialign package. It gives you an operation like zipping, but that keeps going until both lists run out. It also generalizes to types other than lists, such as rose trees. In your case, you'd use it like this:
import Data.Semialign
import Data.These
addLists :: (Semialign f, Num a) => f a -> f a -> f a
addLists = alignWith (mergeThese (+))
longZip :: Semialign f => (a -> a -> a) -> f a -> f a -> f a
longZip = alignWith . mergeThese
The new type signatures are optional. If you want, you can keep using your old ones that restrict them to lists.

Haskell list to unitary sublist

I'm having problems turning a list to a unitary sublist
sublists :: [a] -> [[a]]
sublists [] = [[]]
sublists (x:xs) = [x:ys | ys <- sub] ++ sub
where sub = sublists xs
I need a function that given
sublists [True,False]
returns
[[True],[False]] instead of [[True,False],[True],[False],[]]
But I just don´t know how and feel like punching my computer in the face.
I hope I am clear. Thanks!
So you want a function that converts a to [a]. Okay...
makeList = \x -> [x]
(why did I write it as a lambda? keep reading)
So you want a function that converts a to [a] within a list. Okay...
makeListsInList = map (\x -> [x])
done.
You can use the function pure :: Applicative f => a -> f a to wrap values into a list, since the instance of Applicative for [] wraps elements in a singleton list.
So you can define your function as:
sublists :: [a] -> [[a]]
sublists = map pure
For example:
Prelude> sublists [True, False, False, True]
[[True],[False],[False],[True]]

How do I generate all combinations of list elements to a given length with iterate?

I'm trying to write a function using iterate which should generate all combinations of the elements:
f :: [a] -> [[[a]]]
f [1,2] =
[ [[1] , [2]] -- all combinations of length 1
, [[1,1],[1,2],[2,1],[2,2]], -- all combinations of length 2
, [[1,1,1],... ] -- all combinations of length 3
, ... -- and so on
] -- infinitely
I've tried the following approach
f :: [a] -> [[[a]]]
f list = iterate genLists list
genLists :: [a] -> [[a]]
genLists list = [ [k] | k<-list ]
However, Hugs gives me the following error:
Type error in application
*** Expression : iterate genLists list
*** Term : genLists
*** Type : [a] -> [[a]]
*** Does not match : [[a]] -> [[a]]
*** Because : unification would give infinite type
I don't really know why I get the error. Also, how can I generate those combinations using only iterate? I cannot import any other module since this is an assignment.
Lets see why you get the error:
iterate :: (a -> a ) -> a -> [a]
genLists :: [a] -> [[a]]
As you can see, iterate takes a function that takes and returns the same type. However, genLists doesn't do that. It takes a list and returns a list of lists.
Since you actually want f :: [a] -> [[[a]]], genLists return type is actually fine. However, its argument type is wrong. It has to be of type genLists :: [[a]] -> [[a]]:
f :: [a] -> [[[a]]]
f xs = iterate genLists [[x] | x <- xs]
where
genLists yss = [ x : ys | x <- xs , ys <- yss]
Here is one possible implementation, using the applicative style (which you can learn more about here).
import Control.Applicative
f :: [a] -> [[[a]]]
f xs = iterate genLists $ map pure xs
where
genLists xss = (:) <$> xs <*> xss
Then,
λ> take 3 $ f [1,2]
[[[1],[2]],[[1,1],[1,2],[2,1],[2,2]],[[1,1,1],[1,1,2],[1,2,1],[1,2,2],[2,1,1],[2,1,2],[2,2,1],[2,2,2]]]
Here is an alternative, if you don't want to or cannot use applicative stuff:
f :: [a] -> [[[a]]]
f xs = iterate genLists $ map (\x -> [x]) xs
where
genLists xss = [y : ys | y <- xs, ys <- xss]

Is there a function that takes a list and returns a list of duplicate elements in that list?

Is there a Haskell function that takes a list and returns a list of duplicates/redundant elements in that list?
I'm aware of the the nub and nubBy functions, but they remove the duplicates; I would like to keep the dupes and collects them in a list.
The simplest way to do this, which is extremely inefficient, is to use nub and \\:
import Data.List (nub, (\\))
getDups :: Eq a => [a] -> [a]
getDups xs = xs \\ nub xs
If you can live with an Ord constraint, everything gets much nicer:
import Data.Set (member, empty, insert)
getDups :: Ord a => [a] -> [a]
getDups xs = foldr go (const []) xs empty
where
go x cont seen
| member x seen = x : r seen
| otherwise = r (insert x seen)
I wrote these functions which seems to work well.
The first one return the list of duplicates element in a list with a basic equlity test (==)
duplicate :: Eq a => [a] -> [a]
duplicate [] = []
duplicate (x:xs)
| null pres = duplicate abs
| otherwise = x:pres++duplicate abs
where (pres,abs) = partition (x ==) xs
The second one make the same job by providing a equality test function (like nubBy)
duplicateBy :: (a -> a -> Bool) -> [a] -> [a]
duplicateBy eq [] = []
duplicateBy eq (x:xs)
| null pres = duplicateBy eq abs
| otherwise = x:pres++duplicateBy eq abs
where (pres,abs) = partition (eq x) xs
Is there a Haskell function that takes a list and returns a list of duplicates/redundant elements in that list?
You can write such a function yourself easily enough. Use a helper function that takes two list arguments, the first one of which being the list whose dupes are sought; walk along that list and accumulate the dupes in the second argument; finally, return the latter when the first argument is the empty list.
dupes l = dupes' l []
where
dupes' [] ls = ls
dupes' (x:xs) ls
| not (x `elem` ls) && x `elem` xs = dupes' xs (x:ls)
| otherwise = dupes' xs ls
Test:
λ> dupes [1,2,3,3,2,2,3,4]
[3,2]
Be aware that the asymptotic time complexity is as bad as that of nub, though: O(n^2). If you want better asymptotics, you'll need an Ord class constraint.
If you are happy with an Ord constraint you can use group from Data.List:
getDups :: Ord a => [a] -> [a]
getDups = concatMap (drop 1) . group . sort

Duplicates removal with foldl

I'm trying to write my implementation of remdps, function, which removes nearest duplicates in a list. For example: "aaabbbsscaa" should became "absca". I have to use foldl. Here is my attempt:
helper :: Eq a => [a] -> a -> [a]
helper [] ele = [ele]
helper newlist ele = if tail newlist /= ele then newlist:ele
else newlist
remdps :: Eq a => [a] -> [a]
remdps list = foldl helper [] list
main = putStrLn (show (remdps "aabssscdddeaffff"))
And the error:
4.hs:4:41:
Could not deduce (a ~ [a])
from the context (Eq a)
bound by the type signature for helper :: Eq a => [a] -> a -> [a]
at 4.hs:2:11-33
`a' is a rigid type variable bound by
the type signature for helper :: Eq a => [a] -> a -> [a]
at 4.hs:2:11
In the second argument of `(/=)', namely `ele'
In the expression: tail newlist /= ele
In the expression:
if tail newlist /= ele then newlist : ele else newlist
4.hs:4:50:
Could not deduce (a ~ [a])
from the context (Eq a)
bound by the type signature for helper :: Eq a => [a] -> a -> [a]
at 4.hs:2:11-33
`a' is a rigid type variable bound by
the type signature for helper :: Eq a => [a] -> a -> [a]
at 4.hs:2:11
In the first argument of `(:)', namely `newlist'
In the expression: newlist : ele
In the expression:
if tail newlist /= ele then newlist : ele else newlist
4.hs:4:58:
Could not deduce (a ~ [a])
from the context (Eq a)
bound by the type signature for helper :: Eq a => [a] -> a -> [a]
at 4.hs:2:11-33
`a' is a rigid type variable bound by
the type signature for helper :: Eq a => [a] -> a -> [a]
at 4.hs:2:11
In the second argument of `(:)', namely `ele'
In the expression: newlist : ele
In the expression:
if tail newlist /= ele then newlist : ele else newlist
fish: Unknown command './4'
ghc 4.hs; and ./4
The question is always the same:). What's wrong?
//edit
OK, I have a working code. It uses reverse and ++, so it's very ugly:).
helper :: Eq a => [a] -> a -> [a]
helper [] ele = [ele]
helper newlist ele = if head (reverse newlist) /= ele then newlist ++ [ele]
else newlist
remdps :: Eq a => [a] -> [a]
remdps list = foldl helper [] list
main = putStrLn (show (remdps "aabssscdddeaffff"))
What you're probably trying to do is this:
helper :: Eq a => [a] -> a -> [a]
helper [] ele = [ele]
helper newlist ele = if last newlist /= ele then newlist ++ [ele]
else newlist
The changes:
: works only in one way: on the left is the head of the list (type a), on the right the tail (type [a]). It's sometimes also called "cons". What you want to do is called "snoc": on its right is the last element of the list (type a), and on the left the initial part (type [a]).
"snoc" doesn't exist in the Prelude, so instead, you just write it in a different way: newlist ++ [ele]. (Compare this to x : xs == [x] ++ xs.)
tail newlist == ele becomes last newlist == ele. tail gets the list without its head, but you want to compare the last element of newlist. For that purpose, you have last. (By the way, to get the initial part of a list, you can use init.)
Note that you've also swapped the branches of your if-statement, leaving you with aaa as the answer. -edit- I see that you've updated that now ;)
Also note that this is a very slow approach. Every "snoc" and last will take longer as the answer of remdps grows, because Prelude lists are much better at "cons" and head. Try rewriting the function so that it uses "cons" instead. Hint: you'll need reverse at some point.
Furthermore, this function will not work when used with infinite lists, because of the way foldl works. It might be an interesting exercise to rewrite this function to use foldr instead.
The type annotation of helper suggest that ele is of type a
And you do the following test (tail(newlist) == ele), but tail if of type [a]
You cannot compare two value if different type.
This is not the only error.
I suggest you take a look at the docs for Data.List. Specifically for tail you'll see that the type is [a] -> [a], so obviously it doesn't return the last element of the list as one might think.
If you're looking to get a single element of out of a list (the last one) you need something with type [a] -> a. The power of haskell comes from the fact that this information is almost enough to find the right function.
Just Hoogle it!
P.S. As a side note - this approach is quite slow, as mentioned in Tinctorius' answer
To expand on my second comment, though this doesn't answer your question as posed, I would very much not use foldl to do this. Back in my Scheme days I'd solve it with this pet kfoldr function of mine, which I've translated to Haskell here:
-- | A special fold that gives you both left and right context at each right
-- fold step. See the example below.
kfoldr :: (l -> a -> l) -> l -> (l -> a -> r -> r) -> (l -> r) -> [a] -> r
kfoldr advance left combine seedRight [] = seedRight left
kfoldr advance left combine seedRight (x:xs) = combine left x (subfold xs)
where subfold = let newLeft = advance left x
in newLeft `seq` kfoldr advance newLeft combine seedRight
removeDuplicates :: Eq a => [a] -> [a]
removeDuplicates = kfoldr advance Nothing step (const [])
where
-- advance is the left context generator, which in this case just
-- produces the previous element at each position.
advance _ x = Just x
-- step's three arguments in this case are:
-- (a) the element to the left of current
-- (b) the current element
-- (c) the solution for the rest of the list
step Nothing x xs = x:xs
step (Just x') x xs
| x == x' = xs
| otherwise = x:xs
Haskell's Data.List library has mapAccumL and mapAccumR which are similar but they map instead of folding. There's also the intimately related scanl and scanr, which can probably be used to implement kfoldr (but I haven't bothered to try).