Haskell "Couldn't match expected type ‘a’ with actual type ‘[a0]’" - haskell

Im doing a project in Haskell where I am trying to create a function which takes two list inputs and then returns a union of the list but without any duplicates.
The problem is that I keep getting the error message:
Couldn't match expected type ‘a’ with actual type ‘[t0]’
‘a’ is a rigid type variable bound by
the type signature for newList :: [a] -> [a] -> [a]
Here is my code:
allList :: (Eq a) => [a] -> [a] -> [a]
allList [] [] = []
allList x y = (x ++ y)
checkDup [] = []
checkDup (z:zs)
| z `elem` zs = checkDup zs
| otherwise = z : checkDup zs
newList :: (Eq a) => [a] -> [a] -> [a]
newList [] [] = []
newList x y = [checkDup z | z <- allList x y]
The first allList function creates a list of the two list, the checkDup creates a new list without any duplicates and the newList uses list comprehension to pass the combined list to the checkDup.
Anyone know where I am going wrong?

The problem lies here:
newList x y = [checkDup z | z <- allList x y]
z is supposed to be a list you pass to checkDup, but in this case, z is just a single element
Maybe you want:
newList x y = checkDup $ allList x y
newList can be declared as follows:
newList :: (Eq a) => [a] -> [a] -> [a]
newList = checkDup . allList

Since #Smac89 answered your question, why not use a data representation like Data.Set?
import qualified Data.Set as S
allList :: Ord a => [a] -> [a] -> [a]
allList xs ys = S.toList $ S.union (S.fromList xs) (S.fromList ys)
(although the continued use of Sets is probably even more meaningful.)
Or by using Data.List:
import Data.List
newList :: Eq a => [a] -> [a] -> [a]
newList xs ys = nub $ xs ++ ys

Related

Get duplicated elements in a list without using (Ord a)

I have been trying to make a function that concatenates a list of lists, sorts it, and gives back the duplicated values.
The issue I'm facing is that it tells me to change (Eq a) to (Ord a) for the last function, but I cannot do this. How can I solve this without changing (Eq a) to (Ord a) ?
This is the code I have:
group :: Eq a => [a] -> [[a]]
group = groupBy (==)
groupBy :: (a -> a -> Bool) -> [a] -> [[a]]
groupBy _ [] = []
groupBy eq (x:xs) = (x:ys) : groupBy eq zs
where (ys,zs) = span (eq x) xs
uniq :: Eq b => [b] -> [b]
uniq = map head . group
insert :: Ord a => a -> [a] -> [a]
insert x [] = [x]
insert x (y:ys) | x < y = x:y:ys
| otherwise = y:(insert x ys)
isort :: (Eq a, Ord a) => [a] -> [a]
isort [] = []
isort (x:xs) = insert x (isort xs)
kms :: Ord a => [a]
kms xss = uniq (isort (concat xss))
pairwiseIntersections :: (Eq a) => [[a]] -> [a]
pairwiseIntersections xss = kms xss
You cannot sort a list without its elements having some ordering -- meaning that they must be instances of Ord.
You can do other things to deduplicate a list, like nub, but if you want it sorted you need Ord or an equivalent ordering.
You mention no complexity requirements, so the simplest approach could be
keepOnlyDups [] = []
keepOnlyDups (x:xs) = [x | elem x xs] ++ keepOnlyDups [ y | y <- xs, y /= x]
removeExtras [] = []
removeExtras (x:xs) = [x] ++ removeExtras [ y | y <- xs, y /= x]
answering both your question's text and the implied meaning of the code.
Implementing keepOnlyUniques is left as an exercise, if you're interested in that.

Prevent repeat printing of common list variables Haskell

Currently, I am making a function that can take the values in two lists, compare them, and print any similar values. If a value is duplicated in both lists, it is not printed a second time.
EXAMPLE
INPUT: commons [1,2,2,3,4] [2,3,4,5,2,6,8]
EXPECTED OUTPUT: [2,3,4]
What I currently have causes a repeated values in both lists to repeat in the output. So, in the above example, the 2 would print twice.
Here is the current code I am working on:
commons :: Eq a => [a] -> [a] -> [a]
commons [] [] = []
commons x y = commons_Helper x y
commons_Helper :: Eq a => [a] -> [a] -> [a]
commons_Helper [] [] = []
commons_Helper x [] = []
commons_Helper [] y = []
commons_Helper (x:xs) y =
if elem x y then x : commons_Helper xs y
else commons_Helper xs y
Any and all help would be greatly appreciated.
EDIT: This must remain as commons :: Eq a => [a] -> [a] -> [a], and I cannot import and libraries
You could make your traversal of the xs list a stateful one, the state keeping track of elements that have been already seen. The state begins life as an empty list.
It is possible to do that by adding a 3rd parameter to your helper function, which currently is not very useful.
commons_Helper :: Eq a => [a] -> [a] -> [a] -> [a]
commons_Helper [] ys st = []
commons_Helper (x:xs) ys st =
if (elem x ys && (not $ elem x st)) -- extra test here
then x : (commons_Helper xs ys (x:st))
else commons_Helper xs ys st
commons :: Eq a => [a] -> [a] -> [a]
commons xs ys = commons_Helper xs ys []
This state-based technique is very common in Haskell. There is even a library function: mapAccumL :: (s -> a -> (s, b)) -> s -> [a] -> (s, [b]) to support it.

How to remove second largest element in a list in haskell?

I have created a program to remove first smallest element but I dont how to do for second largest:
withoutBiggest (x:xs) =
withoutBiggestImpl (biggest x xs) [] (x:xs)
where
biggest :: (Ord a) => a -> [a] -> a
biggest big [] = big
biggest big (x:xs) =
if x < big then
biggest x xs
else
biggest big xs
withoutBiggestImpl :: (Eq a) => a -> [a] -> [a] -> [a]
withoutBiggestImpl big before (x:xs) =
if big == x then
before ++ xs
else
withoutBiggestImpl big (before ++ [x]) xs
Here is a simple solution.
Prelude> let list = [10,20,100,50,40,80]
Prelude> let secondLargest = maximum $ filter (/= (maximum list)) list
Prelude> let result = filter (/= secondLargest) list
Prelude> result
[10,20,100,50,40]
Prelude>
A possibility, surely not the best one.
import Data.Permute (rank)
x = [4,2,3]
ranks = rank (length x) x -- this gives [2,0,1]; that means 3 (index 1) is the second smallest
Then:
[x !! i | i <- [0 .. length x -1], i /= 1]
Hmm.. not very cool, let me some time to think to something better please and I'll edit my post.
EDIT
Moreover my previous solution was wrong. This one should be correct, but again not the best one:
import Data.Permute (rank, elems, inverse)
ranks = elems $ rank (length x) x
iranks = elems $ inverse $ rank (length x) x
>>> [x !! (iranks !! i) | i <- filter (/=1) ranks]
[4,2]
An advantage is that this preserves the order of the list, I think.
Here is a solution that removes the n smallest elements from your list:
import Data.List
deleteN :: Int -> [a] -> [a]
deleteN _ [] = []
deleteN i (a:as)
| i == 0 = as
| otherwise = a : deleteN (i-1) as
ntails :: Int -> [a] -> [(a, Int)] -> [a]
ntails 0 l _ = l
ntails n l s = ntails (n-1) (deleteN (snd $ head s) l) (tail s)
removeNSmallest :: Ord a => Int -> [a] -> [a]
removeNSmallest n l = ntails n l $ sort $ zip l [0..]
EDIT:
If you just want to remove the 2nd smallest element:
deleteN :: Int -> [a] -> [a]
deleteN _ [] = []
deleteN i (a:as)
| i == 0 = as
| otherwise = a : deleteN (i-1) as
remove2 :: [a] -> [(a, Int)] -> [a]
remove2 [] _ = []
remove2 [a] _ = []
remove2 l s = deleteN (snd $ head $ tail s) l
remove2Smallest :: Ord a => [a] -> [a]
remove2Smallest l = remove2 l $ sort $ zip l [0..]
It was not clear if the OP is looking for the biggest (as the name withoutBiggest implies) or what. In this case, one solution is to combine the filter :: (a->Bool) -> [a] -> [a] and maximum :: Ord a => [a] -> a functions from the Prelude.
withoutBiggest l = filter (/= maximum l) l
You can remove the biggest elements by first finding it and then filtering it:
withoutBiggest :: Ord a => [a] -> [a]
withoutBiggest [] = []
withoutBiggest xs = filter (/= maximum xs) xs
You can then remove the second-biggest element in much the same way:
withoutSecondBiggest :: Ord a => [a] -> [a]
withoutSecondBiggest xs =
case withoutBiggest xs of
[] -> xs
rest -> filter (/= maximum rest) xs
Assumptions made:
You want each occurrence of the second-biggest element removed.
When there is zero/one element in the list, there isn't a second element, so there isn't a second-biggest element. Having the list without an element that isn't there is equivalent to having the list.
When the list contains only values equivalent to maximum xs, there also isn't a second-biggest element even though there may be two or more elements in total.
The Ord type-class instance implies a total ordering. Otherwise you may have multiple maxima that are not equivalent; otherwise which one is picked as the biggest and second-biggest is not well-defined.

How to extract the same elements from two lists in Haskell?

here's my question:
How to extract the same elements from two equal length lists to another list?
For example: given two lists [2,4,6,3,2,1,3,5] and [7,3,3,2,8,8,9,1] the answer should be [1,2,3,3]. Note that the order is immaterial. I'm actually using the length of the return list.
I tried this:
sameElem as bs = length (nub (intersect as bs))
but the problem is nub removes all the duplications. The result of using my function to the former example is 3 the length of [1,3,2] instead of 4 the length of [1,3,3,2]. Is there a solution? Thank you.
Since the position seems to be irrelevant, you can simply sort the lists beforehand and then traverse both lists:
import Data.List (sort)
intersectSorted :: Ord a => [a] -> [a] -> [a]
intersectSorted (x:xs) (y:ys)
| x == y = x : intersectSorted xs ys
| x < y = intersectSorted xs (y:ys)
| x > y = intersectSorted (x:xs) ys
intersectSorted _ _ = []
intersect :: Ord a => [a] -> [a] -> [a]
intersect xs ys = intersectSorted (sort xs) (sort ys)
Note that it's also possible to achieve this with a Map:
import Data.Map.Strict (fromListWith, assocs, intersectionWith, Map)
type Counter a = Map a Int
toCounter :: Ord a => [a] -> Counter a
toCounter = fromListWith (+) . flip zip (repeat 1)
intersectCounter :: Ord a => Counter a -> Counter a -> Counter a
intersectCounter = intersectionWith min
toList :: Counter a -> [a]
toList = concatMap (\(k,c) -> replicate c k) . assocs
intersect :: Ord a => [a] -> [a] -> [a]
intersect xs ys = toList $ intersectCounter (toCounter xs) (toCounter ys)
You could write a function for this. There is probably a more elegant version of this involving lambda's or folds, but this does work for your example:
import Data.List
same (x:xs) ys = if x `elem` ys
then x:same xs (delete x ys)
else same xs ys
same [] _ = []
same _ [] = []
The delete x ys in the then-clause is important, without that delete command items from the first list that occur at least once will be counted every time they're encountered.
Note that the output is not sorted, since you were only interested in the length of the resulting list.
import Data.List (delete)
mutuals :: Eq a => [a] -> [a] -> [a]
mutuals [] _ = []
mutuals (x : xs) ys | x `elem` ys = x : mutuals xs (delete x ys)
| otherwise = mutuals xs ys
gives
mutuals [2,4,6,3,2,1,3,5] [7,3,3,2,8,8,9,1] == [2,3,1,3]

Using few functions in Haskell together

I made this code where I need to find elements in a list that appears only once
for example: for input [1,2,2,3,4,4], the output will be: [1,3]
unique :: =[a]->[a]
unique xs =[x|x<-xs, elemNum x xs ==1]
elemNum :: Int -> [Int]->[Int]
elemNum x (y:ys)
| x==y =1+ elemNum x ys
| otherwise =elemNum x ys
However I am getting an error :
Not in scope: `unique'
Is this the correct way to use 2 function in Haskell? (define them at the same file), What'a wrong with the code?
There are a few problems in your code:
type signature of unique is wrong, it should be
unique :: (Eq a) => [a] -> [a]
that type constraint (Eq a) comes from elemNum
type signature of elemNum also wrong, it should be
elemNum :: (Eq a) => a -> [a] -> Int
that type constraint comes from ==, and the type of its first parameter no need to be Int, but its return type should be Int because you want to find out how many x in xs.
Also, you forgot to deal with empty list in that definition.
Here is a fixed version of your code:
unique :: (Eq a) => [a] -> [a]
unique xs =[x| x<-xs, elemNum x xs == 1]
elemNum :: (Eq a) => a -> [a] -> Int
elemNum x [] = 0
elemNum x (y:ys)
| x==y = 1 + elemNum x ys
| otherwise = elemNum x ys
Here is another implementation:
onlyOnce [] = []
onlyOnce (x:xs)
| x `elem` xs = onlyOnce $ filter (/=x) xs
| otherwise = x : onlyOnce xs
If x occurs in xs, then the result of onlyOnce (x:xs) should be the same as the result of applying onlyOnce to the result of removing all occurrences of x from xs; otherwise, x occurs in (x:xs) only once, so x should be part of the final result.
You have an equals sign in the Type declaration for unique:
unique :: =[a]->[a]
should be
unique :: [a] -> [a]
In my opinion it is much easier to implement this function using functions from Data.List module:
import Data.List
unique :: (Ord a) => [a] -> [a]
unique = map (\(y,_) -> y) . filter (\(x,l) -> l == 1) . map (\l#(x:xs) -> (x,length l)) . group . sort

Resources