Pattern matching a singleton list, equivalent/erroneous statements - list

For context I am trying to create a simple function that outputs the elements of a list at even numbered locations.
>evens [] = []
>evens [x] = x
>evens (x, y, xs) = x : evens xs
Why does this throw a type error on compilation?
I change the second line to:
>evens [x] = x:[]
and everything then works absolutely fine.
learnyouahaskell.com states that in pattern matching, (x:[]) can be rewritten as [x] but why does this fail in my function definition?

[x] != x. A list of one element is different from the element itself. You can replace the x:[] with [x], but you can't replace [x] with x! Also, your third equation seems wrong. You say it compiles fine, so it might be a typo, but, to be sure, here's the full definition of evens:
evens :: [a] -> [a]
evens [] = []
evens [x] = [x] -- x :: a; you can't use an a where you need a [a]!
evens (x:y:xs) = x : evens xs
-- x :: a; xs :: [a]; evens xs :: [a]; (:) :: a -> [a] -> [a]
-- x : evens xs :: [a]

Related

Haskell: Sort list

I am new to Haskell. Can I fix this recursive function to sort all the integers in the array? If yes, how should the code be?
isort [] = []
isort [x] = [x]
isort (x:y:xs) = if x <= y then
x:isort (y:xs)
else
y:isort (x:xs)
Input in current function
isort [4,3,2,1]
gives as output now
[3,2,1,4]
But it should be
[1,2,3,4]
Probably the smallest change to the code to let this sort a list is each time selecting the mymin of the list and yield this as first item of the result and recurse on the list, so:
mymin :: Ord a => [a] -> (a, [a])
mymin [x] = (x, [])
mymin (x:xs)
| x <= y = (x, xs) -- select a new minimum
| otherwise = (y, x:ys) -- use the minimum of the tail of the list
where ~(y, ys) = mymin xs
then we can work with:
isort :: Ord a => [a] -> [a]
isort [] = []
isort xs = y : isort ys
where (y, ys) = mymin xs
This is an implementation of selection sort [wiki] and thus runs in O(n2). I leave it as an exercise to implement faster algorithms like merge sort and Timsort.
Sort and insert one element in array
insert x [] = [x]
insert i (x:xs) = if i<=x then
i:x:xs
else
x:insert i xs
Loop insert function on the whole array
isort [] = []
isort (x:xs) = insert x (isort xs)

infinite type error reversing a list in Haskell

I'm trying to implement the reverse of a list:
myLast :: [a] -> a
myLast [] = error "No end for empty lists!"
myLast [x] = x
myLast (_:xs) = myLast xs
myReverse :: [a] -> [a]
myReverse (x:xs) = myLast xs + myReverse xs
but I get this error:
/workspaces/hask_exercises/exercises/src/Lib.hs:42:32: error:
* Occurs check: cannot construct the infinite type: a ~ [a]
* In the second argument of `(+)', namely `myReverse xs'
In the expression: myLast xs + myReverse xs
In an equation for `myReverse':
myReverse (x : xs) = myLast xs + myReverse xs
* Relevant bindings include
xs :: [a] (bound at src/Lib.hs:42:14)
x :: a (bound at src/Lib.hs:42:12)
myReverse :: [a] -> [a] (bound at src/Lib.hs:41:1)
|
42 | myReverse (x:xs) = myLast xs + myReverse xs
| ^^^^^^^^^^^^
What does it mean that cannot construct the infinite type: a ~ [a]? I get this error a lot and would like to understand what it means.
The (+) :: Num a => a -> a -> a function adds two numbers (of the same type) together. So for example if a ~ Int, it will add two Ints together, but not an Int and a [Int].
But even if the (+) operator for example would prepend an item to a list, it would still not reverse the list correctly: your function has no base case what to do for an empty list, and your recursive list does nothing with the first item x of the list (x:xs).
A simple way to reverse:
myReverse :: [a] -> [a]
myReverse [] = []
myReverse (x:xs) = myReverse xs ++ [x]
But that is not efficient: appending two items will take linear time in the size of the left list. You can work with an accumulator: a parameter that you each time update when you make a recursive call. This looks like:
myReverse :: [a] -> [a]
myReverse [] = go []
where go ys (x:xs) = …
where go ys [] = …
where filling in the … parts are left as an exercise.
You have
myLast :: [a] -> a
myReverse :: [a] -> [a]
myReverse (x:xs) = myLast xs + myReverse xs
\___a___/ \____[a]___/
(x:xs) :: [a]
---------------
x :: a
xs :: [a] xs :: [a]
myLast :: [a] -> a myReverse :: [a] -> [a]
------------------------- ----------------------------
myLast xs :: a myReverse xs :: [a]
myReverse (x:xs) :: [a]
but
> :t (+)
(+) :: Num a => a -> a -> a
which means that the type of the thing on the left of + and the type of the thing on the right must be the same.
But they can't be: as we just saw above, in your code the first (of myLast xs) is some type a, and the second (of myReverse xs) is [a] the list of those same as.
These two can't be the same, because it would mean
a ~ [a] OK, this is given to us, then
a ~ [a] we can use it, so that
--------------
a ~ [[a]] this must hold;
a ~ [a] we know this, then
--------------
a ~ [[[a]]] this must also hold; and
a ~ [a] ........
-------------- ........
a ~ [[[[a]]]] ........
.........................
and so on ad infinitum, thus making this a an "infinite" type. Hence the error.
You could fix it by replacing the + with
(+++) :: a -> [a] -> [a]
and implementing it to do what you need it to do.
You will also need to fix your off-by-one error whereby you completely ignore the first element in the received input, x.

Sorting lists in list by length using bubble sort - Haskell

I have an input, which is of type [[a]] and I am trying to sort the lists in the list by their length. I am working on my own implementation of bubble sort, which currently looks like this:
myInput :: Ord a => [[a]] -> [[a]]
myInput [[]] = [[]]
myInput [[x]] = [[x]]
myInput (x : xs) = mySort x (myInput xs)
mySort :: Ord a => [a] -> [[a]] -> [[a]]
mySort x [[]] = [x]
mySort x (y:ys) | (length x) < (length y) = x:y:ys
| otherwise = y:(myInput x ys)
However, when I input myInput[[1,2],[1]], I get a non-exhaustive pattern error:
[[1]*** Exception: CourseworkRev.hs:(197,1)-(200,49): Non-exhaustive patterns in function myInput
I am probably doing something wrong when declaring the empty lists, as this is a recursion error (correct me if I am wrong). Any tips on how to make this working? Thanks!
myInput has no pattern for an empty list, only for a list with one element that is an empty list. You likely do not need patterns like [[]] and [[x]] anyway, since for a list with a single element, you will return a list with that element, regardless of it length, so:
myInput :: Ord a => [[a]] -> [[a]]
myInput [] = []
myInput [x] = [x]
myInput (x : xs) = mySort x (myInput xs)
[[x]] matches with a list that contains exactly one sublist [x] which is a list with one element. So this will match with [[1]], but not with [[1,2]]. [x] on the other hand matches with any singleton list: a list with one element so [[1]], [[1,4]], [[1,4,2,5]], and [[]] will all match.

predicate and a list search haskell

I am learning Haskell at the moment and have come to a bit of a standstill. I'm trying to write a function that takes a predicate p and a list xs and returns the list of those elements of xs which immediately follow an element which passes the predicate p. Here is what I have :
afterFilter :: (a -> Bool) -> [a] -> [a]
afterFilter x (y:ys) =
if x y
then (map head [ys])
else
afterFilter x (tail ys)
test input : afterFilter (<0) [-4,7,-4,-8,3,-3,-6,0,-9,-1]
output : [7]
The trick is to pull two elements out of the input list by pattern-matching two cons cells. If the first element passes the predicate, we stick the second on the output. But don't forget to stick the second element back on the input list when you make the recursive call.
afterFilter :: (a -> Bool) -> [a] -> [a]
afterFilter f [] = [] -- input list is empty
afterFilter f [x] = [] -- input list has only one element - no "next element" to return
afterFilter f (x:y:xs) =
let ys = afterFilter f (y:xs)
in (if f x then y:ys else rest)
However, a higher-level - and much more Haskellish - way to approach the problem would be to break it down into a pipeline of operations.
Pair up each item in the list with the element that follows it using zip, so we have a list of (element, next) pairs.
Use filter to drop the pairs for which element does not pass the predicate.
Use map to extract the next part of each surviving pair.
So the code looks like this:
pairWithSuccessors :: [a] -> [(a, a)]
pairWithSuccessors xs = zip xs (tail xs)
afterFilter :: (a -> Bool) -> [a] -> [a]
afterFilter p xs =
let withSuccessors = pairWithSuccessors xs (tail xs)
filtered = filter (\(element, next) -> p element) withSuccessors
filteredSuccessors = map (\(element, next) -> next) filtered
in filteredSuccessors
Or, written in point-free style:
afterFilter p = map snd . filter (p . fst) . pairWithSuccessors
Functions built with the composition operator . are read right-to-left: first pairWithSuccessors, then filter (p . fst), then map snd over the result.
GHC is good at working with lists: when compiled with optimisations, both approaches should produce roughly the same machine code - that is, there's no performance cost to the high-level solution
Following what you did, there are some strange things with your code :
The map head [ys] is very odd, and causes your function to stop : At the first element matching the predicate, your function returns a list containing its immediate successor and stops there. You still need to process the rest of the list.
Also, following your definition of the problem, each item which is a successor of an item passing the predicate should be on the resulting array. I may be wrong, but what I understood is that afterFilter (<0) [-1, -1, 1] should return [-1, 1].
However, you're discarding one element you didn't check for by calling tail ys : You checked for y, but not for head ys.
Finally, by adding the edge cases, here is what you get :
afterFilter :: (a -> Bool) -> [a] -> [a]
afterFilter _ [] = []
afterFilter _ [_] = []
afterFilter x (y:ys#(z:zs)) =
if x y
then z : afterFilter x ys
else
afterFilter x ys
Try:
afterFilter :: (a -> Bool) -> [a] -> [a]
afterFilter p [] = []
afterFilter p [_] = []
afterFilter p (x1:x2:xs)
| p x1 = x2:rest
| otherwise = rest
where rest = afterFilter p (x2:xs)
Or
afterFilter' :: (a -> Bool) -> [a] -> [a]
afterFilter' p xs = map snd $ filter (\(x, _) -> p x) $ zip xs (tail xs)
Or
afterFilter'' :: (a -> Bool) -> [a] -> [a]
afterFilter'' p xs = [y | (x, y) <- zip xs (tail xs), p x]

Finding the Highest number of two lists-haskell

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
λ>