How to fix '*** Exception: Prelude.head: empty list' here - haskell

This is a homework , it's to removing the adjacent duplicates.
The result should like this removeAdjacentDuplicates [3,1,2,2,2,2,2,4,4,2,2,3] == [3,1,2,4,2,3]
I knew it's not necessary to use head here, but it's not allowed to use rekursion and List-Comprehensions of Form [e | ...]. Only the function in Prelude is permittet, group und so on , which in other packages are also not allowed. map zip filter concat reverse foldr are recommended.
For example , It's not possible to make this:
removeAdjacentDuplicates :: Eq a => [a] -> [a]
removeAdjacentDuplicates (x:xs#(y:_))
| x == y = x:tail (removeAdjacentDuplicates xs)
| otherwise = x:removeAdjacentDuplicates xs
so I try like this
removeAdjacentDuplicates = foldr (\x result -> if ( x == (head result)) then result else (x : result)) []
but when I test it, it throw *** Exception: Prelude.head: empty list' here out
I have tried to add removeAdjacentDuplicates [] = [] before,
But error is like this
Equations for ‘removeAdjacentDuplicates’ have different numbers of arguments
H7-1.hs:24:1-32
H7-1.hs:25:1-105
|
24 | removeAdjacentDuplicates [] = []
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^...
I don't understand where the problem is, and how can I solve it?

x == head result dies if result is [] -- and result is definitely [] in the first iteration of foldr, so adding a special case for when the input list would not require foldr to do any iterations is fixing exactly the wrong case!
Instead of trying to extract a value from the result list, you could insert x into a list; so consider using the condition
[x] == take 1 result
instead -- it never dies.

As said by #DanielWagner, head :: [a] -> a will raise an error for empty lists. We can solve this by using take :: Int -> [a] -> [a], or by using pattern matching:
removeAdjacentDuplicates :: (Foldable f, Eq a) => f a -> [a]
removeAdjacentDuplicates = foldr f []
where f x ys#(y:_) | x == y = ys
f x ys = (x:ys)
here ys#(y:_) will match given the list is non-empty, with y as head of the list. In that case we thus check if x == y, and if that holds, we return ys. Otherwise we return (x:ys).

Related

Symmetric Relation in Haskell

I'm working with relations and I want to find whether a relation is symmetric.
To find that a relation is symmetric, we need to find two tuples such that: [(a,b), (b,a)].
This is what I've got so far:
simmetry:: Eq a => [(a,a)] -> [a]
simmetry [] = []
simmetry (x:xs)
| (fst x `elem` map snd xs) && (snd x `elem` map fst xs) = fst x : (simmetry xs)
| otherwise = simmetry xs
What this function does is, it grabs a tuple x and checks that it finds its first element in another tuple as the second position, as well as checking that the second element is in another tuple as the first position.
However I'm missing out on the part where I have to check that the other tuple is the same one for both conditions. With my code, something like this: [(a,b),(b,c),(d,a)] would work.
P.D: simmetry returns [a] for testing purposes.
I'm out of ideas, any tips are highly appreciated!
What you want to check is: for every tuple (x,y) in the list, (y,x) should also be present. You can express that quite directly in Haskell:
isSymmetric :: Eq a => [(a,a)] -> Bool
isSymmetric l = all (\(x,y) -> (y,x)`elem`l) l
This is actually doing some redundant work because it always also goes over (x,y) itself, which your not really interested in, but it doesn't really matter. However it's a good exercise to design this in a way so it doesn't go over the element itself; for this it's helpful to use an auxiliary function
foci :: [a] -> [(a,[a])]
witht the behaviour
foci [p,q,r] ≡ [(p,[q,r]), (q,[p,r]), (r,[p,q])]
Then you left with an all over the foci of the input list, i.e.
isSymmetric = all _ . foci
With what #Rik Van Toor said:
simmetry:: Eq a => [(a,a)] -> [a]
simmetry [] = []
simmetry (x:xs)
| (snd x, fst x) `elem` xs = fst x : (simmetry xs)
| otherwise = simmetry xs

Haskell don't really know what to name this

I'm trying to make it so that on a tuple input (n,m) and a list of tuples xs , if the first item in the tuple in xs is in (n,m) then keep it that way in the new list otherwise add the a tuple consisting of some value k from n to m as a first element and as second element it should be 0.My question is:how can i say "repeat 0" using guards ? Since clearly my code won't run since my code says "repeat = 0"
expand :: (Int,Int) -> Profile ->Profile
expand (n,m) [] = zip [n..m] (repeat 0)
expand (n,m) (x:xs) = zip [n..m] (repeat (|(fst (x) `elem` [n..m]) == False = 0
|otherwise = snd (x))
You can use a helper function here that converts a number in the [ n .. m ] range to a 2-tuple. Here we thus try to find an element in the list xs that matches with the first item of that tuple, if we do not find such element, we use 0:
import Data.List(find)
expand :: (Int,Int) -> Profile -> Profile
expand (n,m) xs = map go [n .. m]
where go i | Just l <- find (\(f, _) -> f == i) xs = l
| otherwise = (i, 0)
For a list, find was implemented as [src]:
find :: (a -> Bool) -> [a] -> Maybe a
find p = listToMaybe . filter p
filter thus will make a list that contains the elements that satisfy the predicate p, and listToMaybe :: [a] -> Maybe a will convert an empty list [] to Nothing, and for a non-empty list (x:_) it will wrap the first element x in a Just data constructor. Due to Haskell's laziness, it will thus look for the first element that satisfies the predicate.
this thus gives us:
Prelude Data.List> expand (2,7) [(4, 2.3), (6, 3)]
[(2,0.0),(3,0.0),(4,2.3),(5,0.0),(6,3.0),(7,0.0)]

How to inform GHC that a particular pattern match is impossible (ex: list will never be empty)?

I defined selectionSort function as below, sorting an empty list just results in an empty list and sorting a non-empty list is cons of minimum element and sorted version of rest of the list.
selectionSort :: Ord a => [a] -> [a]
selectionSort xs
| null xs = []
| otherwise = minElem : (selectionSort ys)
where
(minElem, ys) = minf xs
where
minf [x] = (x, [])
minf (x:xs) = let (m ,ms) = minf xs in
if x <= m then (x, xs)
else (m, x:ms)
minf takes a non-empty list and returns a tuple of minimum value and rest of the list.
When i compile this function with -W flag, I get this warning
warning: [-Wincomplete-patterns]
Pattern match(es) are non-exhaustive
In an equation for `minf': Patterns not matched: []
|
24 | minf [x] = (x, [])
| ^^^^^^^^^^^^^^^^^^...
It is straight forward that the function minf is never applied to an empty list, because those cases are caught in null xs = []. Is there any way to inform GHC that the particular case is impossible without using other types (NonEmpty list type) or Maybes
Usually the idea is to "design" types in such way that the number of "impossible patterns" is very small (and prefereably zero).
As a poor man solution, you can rewrite the signature of the function from:
foo :: [a] -> b -- [a] is a non-empty list
to:
foo :: a -> [a] -> b -- head and tail as input
So in this context we can rewrite your function to:
selectionSort :: Ord a => [a] -> [a]
selectionSort [] = []
selectionSort (x:xs) = minElem : selectionSort ys
where (minElem, ys) = minf x xs
minf z [] = (z, [])
minf z za#(z2:zs) = let (m, ms) = minf z2 zs in
if z <= m then (z, za)
else (m, z:ms)
So we here use the first parameter as the head of the list, and the second as the tail. Since the list contains at least one element, this means that the tail can be empty, and hence we can do pattern matching. As a result, we can still use the -Wincomplete-patterns flag to check if all patterns are covered and thus we still have some guarantees by the compiler.
In case you still have no means to design the types properly, you can for example add the pattern and raise a (validation) error:
minf [] = error "Impossible: minf only works with a non-empty list"

Remove a Character Sequence From a String

Consider a function, which takes a string and returns a list of all possible cases in which three subsequent 'X's can be removed from the list.
Example:
"ABXXXDGTJXXXDGXF" should become
["ABDGTJXXXDGXF", "ABXXXDGTJDGXF"]
(The order does not matter)
here is a naive implementation:
f :: String -> [String]
f xs = go [] xs [] where
go left (a:b:c:right) acc =
go (left ++ [a]) (b:c:right) y where -- (1)
y = if a == 'X' && b == 'X' && c == 'X'
then (left ++ right) : acc
else acc
go _ _ acc = acc
I think the main problem here is the line marked with (1). I'm constructing the left side of the list by appending to it, which is generally expensive.
Usually something like this can be solved by this pattern:
f [] = []
f (x:xs) = x : f xs
Or more explicitly:
f [] = []
f (x:right) = x : left where
left = f right
Now I'd have the lists right and left in each recursion. However, I need to accumulate them and I could not figure out how to do so here. Or am I on the wrong path?
A solution
Inspired by Gurkenglas' propose, here is a bit more generalized version of it:
import Data.Bool
removeOn :: (String -> Bool) -> Int -> String -> [String]
removeOn onF n xs = go xs where
go xs | length xs >= n =
bool id (right:) (onF mid) $
map (head mid:) $
go (tail xs)
where
(mid, right) = splitAt n xs
go _ = []
removeOn (and . map (=='X')) 3 "ABXXXDGTJXXXDGXF"
--> ["ABDGTJXXXDGXF","ABXXXDGTJDGXF"]
The main idea seems to be the following:
Traverse the list starting from its end. Make use of a 'look-ahead' mechanism which can examine the next n elements of the list (thus it must be checked, if the current list contains that many elements). By this recursive traversal an accumulating list of results is being enhanced in the cases the following elements pass a truth test. In any way those results must be added the current first element of the list because they stem from shorter lists. This can be done blindly, since adding characters to a result string won't change their property of being a match.
f :: String -> [String]
f (a:b:c:right)
= (if a == 'X' && b == 'X' && c == 'X' then (right:) else id)
$ map (a:) $ f (b:c:right)
f _ = []

Remove the First Value in a List that Meets a Criterion

I'm trying to solve this problem. This function takes two parameters. The first is a function that returns a boolean value, and the second is a list of numbers. The function is supposed to remove the first value in the second parameter that returns true when run with the first parameter.
There's a second function, which does the same thing, except it removes the last value that satisfies it, instead of the first.
I'm fairly certain I have the logic down, as I tested it in another language and it worked, my only problem is translating it into Haskell syntax. Here's what I have:
removeFirst :: (t -> Bool) -> [t] -> [t]
removeFirst p xs = []
removeFirst p xs
| p y = ys
| otherwise = y:removeFirst p ys
where
y:ys = xs
removeLast :: (t -> Bool) -> [t] -> [t]
removeLast p xs = []
removeLast p xs = reverse ( removeFirst p ( reverse xs ) )
I ran:
removeFirst even [1..10]
But instead of getting [1,3,4,5,6,7,8,9,10] as expected, I get [].
What am I doing wrong?
removeFirst p xs = []
This always returns the empty list and it matches all arguments. I think you mean this.
removeFirst _ [] = []
Your first equation,
removeFirst p xs = []
says „Whatever my arguments are, just return []“, and the rest of the code is ignored.
You probably mean
removeFirst p [] = []
saying „When the list is already empty, return the empty list.“

Resources