Haskell error: Non-exhausive patterns in function - list

I am trying to implement a list, which searches for a certain pattern in a Tuple (goes through the list of Tuples, empties this and then writes those in, which match the pattern) in the end the list I entered will be empty and then it writes the matching Tuples in this list.
(The functions used do all work - the mistake is in this part)
PatternFinder :: String -> [(String, String)] , [(String, String)]
PatternFinder = n ((b,a) : xs) =
if PatternFits n a
then do
PatternFinder n xs
(b,a) : xs
else PatternFinder n xs

From the text of your question, it seems like you want a simple filter based on the second term of each pair.
patternFinder n = filter (patternFits n . snd)
As an illustration of how this works.
filter ((==1) . snd) [('a',1),('b',2),('c',1)]
returns [('a',1),('c',1)]
In Chad Gilberts answer, however, there is no recursion in the then clause:
if patternFits n a
then (b,a) : xs
else patternFinder n xs
This will return the suffix of the list after the first match. If this is the intended behavior, you could use instead:
patternFinder n = dropwhile (not . patternFits n . snd)
As an example of this:
dropWhile (not . (==2) . snd) [('a',1),('b',2),('c',1)]
returns [('b',2),('c',1)]
Also, in the text of your question you require that the list you entered will be empty. Note that these functions do nothing to the original list but return new lists.

You are not the case of the second argument being the empty list. In order to be exhaustive, you have to handle this pattern:
patternFinder n []
You've also got other syntax errors. Function names must start with a lowercase letter, signatures are separated by ->, not ,, and you don't need a do statement because you're not in a monad context. It should probably look more like this:
patternFinder :: String -> [(String, String)] -> [(String, String)]
patternFinder n [] = []
patternFinder n ((b,a) : xs) =
if patternFits n a
then (b,a) : xs
else patternFinder n xs

Related

How do you write more than 1 line in an if statement in Haskell

I have an if-else statement, and in the else block I want it to first recurse to the function, except for the last two elements of the list, and then return two elements.
In the following function, after the if-else statement, I have 2 lines of code. however this doesnt compile. I believe the compiler reads these two lines as a single line of code. How do you fix that?
doubleEveryOther :: [Integer] -> [Integer] --outputs the input list, but every 2nd element(from the right) is doubled
doubleEveryOther [] = []
doubleEveryOther x = if (length x <2)
then
x
else
doubleEveryOther init (init x) -- These two lines
[2*last(init x), last x] -- These two lines
The compiler says:
* Couldn't match expected type: [Integer]
with actual type: [a0] -> [a0]
* Probable cause: `init' is applied to too few arguments
In the first argument of `doubleEveryOther', namely `init'
In the expression: doubleEveryOther init (init x)
In the expression:
[doubleEveryOther init (init x), 2 * last (init x), last x]
|
19 | [doubleEveryOther init (init x), 2*last(init x), last x]
|
You can not return two lists. If you have two results you want to combine, you use some function, like (++) :: [a] -> [a] -> [a].
That being said, you here don't need this. You can work with simple pattern matching:
doubleEveryOtherFromLeft :: Num a => [a] -> [a]
doubleEveryOtherFromLeft (x:y:xs) = 2*x : y : doubleEveryOtherFromLeft xs
doubleEveryOtherFromLeft xs = xs
then our doubleEveryOther can reverse the list twice:
doubleEveryOther:: Num a => [a] -> [a]
doubleEveryOther = reverse . doubleEveryOtherFromLeft . reverse
I think you are just missing the append operator ++:
doubleEveryOther (init (init x))
++ [2 * last (init x), last x]
I have an if-else statement, and in the else block I want it to first
recurse to the function, except for the last two elements of the list,
and then return two elements
OK. I sort of understand what you're doing. The function name is good - the best name is verb-noun, here doubleEveryOther. However, the code looks a lot like Lisp, probably Scheme - the repeated use of init gives it away. That's not how you write Haskell. (I also write Lisp in Haskell syntax too much...)
Haskell recursion works using pattern matching.
lst = [2,3,4]
1 : [2,3,4] -- [1,2,3,4]
lst = [1,2,3,4]
(x:xs) = lst -- x is 1, xs = [2,3,4]
So, in this case, you want to match your list against x:y:xs:
lst = [1,2,3,4]
(x:y:xs) = lst -- x is 1, y is 2, xs=[3,4]
Hence:
doubleEveryOther :: Num a => [a] -> [a]
doubleEveryOther [] = []
doubleEveryOther [x] = [2*x]
doubleEveryOther (x:y:xs) = (2*x):doubleEveryOther xs
Please note the number of special cases which need to be handled. If I am given an empty list, I should return an empty list. If I am given a single value, I need to double it (in analogy to your if .. else clause). If I am given two or more values, this matches x=first, y=second, xs=[] or more.
As for returning more than one value, you can return only one thing from a function. It can be a single value, a single tuple, a single list, and so on.
In this case, you have written a function which says doubleEveryOther - good - but then you want to return the last two values unchanged. You would be better taking off the last two values, running the simple doubleEveryOther and then bolting the last two values on the end. Otherwise, you are overburdening your function.

Haskell function to keep the repeating elements of a list

Here is the expected input/output:
repeated "Mississippi" == "ips"
repeated [1,2,3,4,2,5,6,7,1] == [1,2]
repeated " " == " "
And here is my code so far:
repeated :: String -> String
repeated "" = ""
repeated x = group $ sort x
I know that the last part of the code doesn't work. I was thinking to sort the list then group it, then I wanted to make a filter on the list of list which are greater than 1, or something like that.
Your code already does half of the job
> group $ sort "Mississippi"
["M","iiii","pp","ssss"]
You said you want to filter out the non-duplicates. Let's define a predicate which identifies the lists having at least two elements:
atLeastTwo :: [a] -> Bool
atLeastTwo (_:_:_) = True
atLeastTwo _ = False
Using this:
> filter atLeastTwo . group $ sort "Mississippi"
["iiii","pp","ssss"]
Good. Now, we need to take only the first element from such lists. Since the lists are non-empty, we can use head safely:
> map head . filter atLeastTwo . group $ sort "Mississippi"
"ips"
Alternatively, we could replace the filter with filter (\xs -> length xs >= 2) but this would be less efficient.
Yet another option is to use a list comprehension
> [ x | (x:_y:_) <- group $ sort "Mississippi" ]
"ips"
This pattern matches on the lists starting with x and having at least another element _y, combining the filter with taking the head.
Okay, good start. One immediate problem is that the specification requires the function to work on lists of numbers, but you define it for strings. The list must be sorted, so its elements must have the typeclass Ord. Therefore, let’s fix the type signature:
repeated :: Ord a => [a] -> [a]
After calling sort and group, you will have a list of lists, [[a]]. Let’s take your idea of using filter. That works. Your predicate should, as you said, check the length of each list in the list, then compare that length to 1.
Filtering a list of lists gives you a subset, which is another list of lists, of type [[a]]. You need to flatten this list. What you want to do is map each entry in the list of lists to one of its elements. For example, the first. There’s a function in the Prelude to do that.
So, you might fill in the following skeleton:
module Repeated (repeated) where
import Data.List (group, sort)
repeated :: Ord a => [a] -> [a]
repeated = map _
. filter (\x -> _)
. group
. sort
I’ve written this in point-free style with the filtering predicate as a lambda expression, but many other ways to write this are equally good. Find one that you like! (For example, you could also write the filter predicate in point-free style, as a composition of two functions: a comparison on the result of length.)
When you try to compile this, the compiler will tell you that there are two typed holes, the _ entries to the right of the equal signs. It will also tell you the type of the holes. The first hole needs a function that takes a list and gives you back a single element. The second hole needs a Boolean expression using x. Fill these in correctly, and your program will work.
Here's some other approaches, to evaluate #chepner's comment on the solution using group $ sort. (Those solutions look simpler, because some of the complexity is hidden in the library routines.)
While it's true that sorting is O(n lg n), ...
It's not just the sorting but especially the group: that uses span, and both of them build and destroy temporary lists. I.e. they do this:
a linear traversal of an unsorted list will require some other data structure to keep track of all possible duplicates, and lookups in each will add to the space complexity at the very least. While carefully chosen data structures could be used to maintain an overall O(n) running time, the constant would probably make the algorithm slower in practice than the O(n lg n) solution, ...
group/span adds considerably to that complexity, so O(n lg n) is not a correct measure.
while greatly complicating the implementation.
The following all traverse the input list just once. Yes they build auxiliary lists. (Probably a Set would give better performance/quicker lookup.) They maybe look more complex, but to compare apples with apples look also at the code for group/span.
repeated2, repeated3, repeated4 :: Ord a => [a] -> [a]
repeated2/inserter2 builds an auxiliary list of pairs [(a, Bool)], in which the Bool is True if the a appears more than once, False if only once so far.
repeated2 xs = sort $ map fst $ filter snd $ foldr inserter2 [] xs
inserter2 :: Ord a => a -> [(a, Bool)] -> [(a, Bool)]
inserter2 x [] = [(x, False)]
inserter2 x (xb#(x', _): xs)
| x == x' = (x', True): xs
| otherwise = xb: inserter2 x xs
repeated3/inserter3 builds an auxiliary list of pairs [(a, Int)], in which the Int counts how many of the a appear. The aux list is sorted anyway, just for the heck of it.
repeated3 xs = map fst $ filter ((> 1).snd) $ foldr inserter3 [] xs
inserter3 :: Ord a => a -> [(a, Int)] -> [(a, Int)]
inserter3 x [] = [(x, 1)]
inserter3 x xss#(xc#(x', c): xs) = case x `compare` x' of
{ LT -> ((x, 1): xss)
; EQ -> ((x', c+1): xs)
; GT -> (xc: inserter3 x xs)
}
repeated4/go4 builds an output list of elements known to repeat. It maintains an intermediate list of elements met once (so far) as it traverses the input list. If it meets a repeat: it adds that element to the output list; deletes it from the intermediate list; filters that element out of the tail of the input list.
repeated4 xs = sort $ go4 [] [] xs
go4 :: Ord a => [a] -> [a] -> [a] -> [a]
go4 repeats _ [] = repeats
go4 repeats onces (x: xs) = case findUpd x onces of
{ (True, oncesU) -> go4 (x: repeats) oncesU (filter (/= x) xs)
; (False, oncesU) -> go4 repeats oncesU xs
}
findUpd :: Ord a => a -> [a] -> (Bool, [a])
findUpd x [] = (False, [x])
findUpd x (x': os) | x == x' = (True, os) -- i.e. x' removed
| otherwise =
let (b, os') = findUpd x os in (b, x': os')
(That last bit of list-fiddling in findUpd is very similar to span.)

Haskell function that outputs all combinations within the input list that add to the input number

I want to write a function in haskell that takes a list of integers and an integer value as input and outputs a list of all the lists that contain combinations of elements that add up to the input integer.
For example:
myFunc [3,7,5,9,13,17] 30 = [[13,17],[3,5,9,13]]
Attempt:
myFunc :: [Integer] -> Integer -> [[Integer]]
myFunc list sm = case list of
[] -> []
[x]
| x == sm -> [x]
| otherwise -> []
(x : xs)
| x + myFunc xs == sm -> [x] ++ myFunc[xs]
| otherwise -> myFunc xs
My code produces just one combination and that combination must be consecutive, which is not what I want to achieve
Write a function to create all subsets
f [] = [[]]
f (x:xs) = f xs ++ map (x:) (f xs)
then use the filter
filter ((==30) . sum) $ f [3,7,5,9,13,17]
[[13,17],[3,5,9,13]]
as suggested by #Ingo you can prune the list while it's generated, for example
f :: (Num a, Ord a) => [a] -> [[a]]
f [] = [[]]
f (x:xs) = f xs ++ (filter ((<=30) . sum) $ map (x:) $ f xs)
should work faster than generating all 2^N elements.
You can use subsequences from Data.List to give you every possible combination of values, then filter based on your requirement that they add to 30.
myFunc :: [Integer] -> Integer -> [[Integer]]
myFunc list sm =
filter (\x -> sum x == sm) $ subsequences list
An alternative would be to use a right fold:
fun :: (Foldable t, Num a, Eq a) => t a -> a -> [[a]]
fun = foldr go $ \a -> if a == 0 then [[]] else []
where go x f a = f a ++ ((x:) <$> f (a - x))
then,
\> fun [3,7,5,9,13,17] 30
[[13,17],[3,5,9,13]]
\> fun [3,7,5,9,13,17] 12
[[7,5],[3,9]]
An advantage of this approach is that it does not create any lists unless it adds up to the desired value.
Whereas, an approach based on filtering, will create all the possible sub-sequence lists only to drop most of them during filtering step.
Here is an alternate solution idea: Generate a list of lists that sum up to the target number, i.e.:
[30]
[29,1]
[28,2]
[28,1,1]
...
and only then filter the ones that could be build from your given list.
Pro: could be much faster, especially if your input list is long and your target number comparatively small, such that the list of list of summands is much smaller than the list of subsets of your input list.
Con: does only work when 0 is not in the game.
Finally, you can it do both ways and write a function that decides which algorthm will be faster given some input list and the target number.

Defining a constant value at begining Haskell function

I have just started learning Haskell and have written two functions, one for lists with even lengths and one for lists odd lengths. This means the 'even' function with [0..7] returns [0,7,2,5,4,3,6,1], and the 'odd' function with [0..8] returns [0,7,2,5,4,3,6,1,8] - these are the results I need.
However I after a lot of work I am still not able to combine them so that just one function works for both lists. Here are the functions and I wondered if more experienced Haskell coders know of a solution.
funcOdd :: [Int] -> [Int]
funcOdd [] = []
funcOdd (x:xs) = take (n+1) ((x*2) : (pred n - x):funcOdd(xs)) where n = length xs
funcEven :: [Int] -> [Int]
funcEven [] = []
funcEven (x:xs) = take (n+1) ((x*2) : (n - x):funcEven(xs)) where n = length xs
You can pattern match to separate the cases
fullFunction theList | even (length theList) = funcEven theList
fullFunction theList = funcOdd theList
when you call fullFunction, it will try the first case, checking if the length of the list is even. If this fails it will fallback to the second case.
Perhaps cleaner this way
func xs = zipWith const (go xs) xs
where go [] = []
go (x:xs) = 2*x : ((length xs)-off-x) : go xs
off = mod (length xs) 2
the only difference I see between the two functions is use of pred n vs n which is replaced with off(set) derived from the length of the original list.
zipWith const ... truncates the result with the length of the original list to replace take (n+1).

How can I find the index where one list appears as a sublist of another?

I have been working with Haskell for a little over a week now so I am practicing some functions that might be useful for something. I want to compare two lists recursively. When the first list appears in the second list, I simply want to return the index at where the list starts to match. The index would begin at 0. Here is an example of what I want to execute for clarification:
subList [1,2,3] [4,4,1,2,3,5,6]
the result should be 2
I have attempted to code it:
subList :: [a] -> [a] -> a
subList [] = []
subList (x:xs) = x + 1 (subList xs)
subList xs = [ y:zs | (y,ys) <- select xs, zs <- subList ys]
where select [] = []
select (x:xs) = x
I am receiving an "error on input" and I cannot figure out why my syntax is not working. Any suggestions?
Let's first look at the function signature. You want to take in two lists whose contents can be compared for equality and return an index like so
subList :: Eq a => [a] -> [a] -> Int
So now we go through pattern matching on the arguments. First off, when the second list is empty then there is nothing we can do, so we'll return -1 as an error condition
subList _ [] = -1
Then we look at the recursive step
subList as xxs#(x:xs)
| all (uncurry (==)) $ zip as xxs = 0
| otherwise = 1 + subList as xs
You should be familiar with the guard syntax I've used, although you may not be familiar with the # syntax. Essentially it means that xxs is just a sub-in for if we had used (x:xs).
You may not be familiar with all, uncurry, and possibly zip so let me elaborate on those more. zip has the function signature zip :: [a] -> [b] -> [(a,b)], so it takes two lists and pairs up their elements (and if one list is longer than the other, it just chops off the excess). uncurry is weird so lets just look at (uncurry (==)), its signature is (uncurry (==)) :: Eq a => (a, a) -> Bool, it essentially checks if both the first and second element in the pair are equal. Finally, all will walk over the list and see if the first and second of each pair is equal and return true if that is the case.