I'm new to Haskell and are playing around a bit. I created a recursive function with guards. See function below:
filterAge :: [Person] -> [String]
filterAge (x:xs)
| (x:xs) == [] = []
| (getAge x) < 30 || (getAge x) > 40 = [] ++ filterAge xs
| otherwise = [getName x] ++ filterAge xs
I have a data set created with 10 Persons which I use in this method. When I tried this function it gave all the right people, but after that it got a Non-exhaustive patterns error:
["Lise","Jaap","Elle","Ebba"*** Exception: D:\...:(44,1)-(47,77): Non-exhaustive patterns in function filterAge
I found out that it never reaches the first guard. So I played around a bit and found out something really strange (in my opinion):
*Main> let (x:xs) = []
*Main> (x:xs) == []
False
Now my main question is: Why does (x:xs) == [] return False?
If anyone has a better way for me of doing the function that'd be great, but it's not very important.
Thanks in advance!
EDIT
Thanks to Willem Van Onsem and Lambda.xy.x I got a quick answer to my question. This resulted in the following function which works perfectly:
filterAge :: [Person] -> [String]
filterAge [] = []
filterAge (x:xs)
| (getAge x) < 30 || (getAge x) > 40 = [] ++ filterAge xs
| otherwise = [getName x] ++ filterAge xs
But for the best version you'd have to check the answer of Willem Van Onsem.
A list is defined as:
data [] a = [] | a : [a]
So there are two constructors for a list: [] the empty list, and (x:xs) a constructor with one element, and a tail that can store an arbitrary number (zero or more) remaining elements.
Therefore (x:xs) is a list with at least one element: the x. The xs can be an empty list (since it has type [a]), but x has type a so that is the "head" of the list. Your let statement works with pattern matching, and since the empty list cannot match with (x:xs), it will always fail.
Another implication is that your first guard can never fire. In order to fix the issue, you should implement a separate case for the empty list. Like:
filterAge :: [Person] -> [String]
filterAge [] = [] -- empty list case
filterAge (x:xs) -- first guard dropped
| (getAge x) < 30 || (getAge x) > 40 = [] ++ filterAge xs
| otherwise = [getName x] ++ filterAge xs
Note that we dropped the first guard in the second clause, since we know that will always fail, and thus checking this will (potentially) only cost CPU cycles.
There are still some parts we can optimize:
we call getAge twice, which is useless, we can use a where clause to optimize this;
[] ++ somelist is simply somelist: appending after an empty list results in that list; and
[element] ++ somelist is element : somelist, since now we work with the list constructor directly.
So our filterAge can be rewritten into:
filterAge :: [Person] -> [String]
filterAge [] = [] -- empty list case
filterAge (x:xs) | age < 30 || age > 40 = filterAge xs
| otherwise = getName x : filterAge xs
where age = getAge x
Note that if you compile (or start the interpreter) with the -Wincomplete-patterns flag (warnings for incomplete patterns), Haskell will automatically warn you that your function definitions are not complete, and that there are input patterns for which you have not defined a clause.
To answer your "main" question,
*Main> let (x:xs) = [] -- (1)
means, when x's or xs's value is required, match (x:xs) with [] and use the resulting bindings. The match will never succeed, and any such attempt will always result in patter-matching failure error.
So why wasn't it?
*Main> (x:xs) == [] -- (2)
Now this means, try to compare (x:xs) and []. Both are lists; comparing lists involves pattern matching the top structure and then proceeding recursively comparing the components, on success -- returning False on failure (not actually failing). Thus a match between (_:_) and [] is tried, and fails, resulting in an immediate return of the False value as the result of the comparison.
Note that values bound to x and xs were not requested at any point; hence there was no error because the matching of (x:xs) and [] in (1) was never triggered.
Related
Given list, break it into lists of identical items next to each other:
[1,1,2,4,5,5] ⟼ [[1,1], [2], [4], [5,5]].
And i need to do that using recursion and without higher order functions.
Here what i've got so far
breakList :: [Int] -> [[Int]]
breakList [] = [[]]
breakList [x] = [[x]]
breakList (x:y:rest)
| x == y = [x] : breakList (y:rest)
| otherwise = [x] : breakList rest
but it does not work.
You can check if the first item of the result of the recursive call has the same value. If that is the case, we prepend that list with x, otherwise we start a "new group" with x as only member of a list, so [x]:
breakList :: Eq a => [a] -> [[a]]
breakList [] = []
breakList [x] = [[x]] -- (1)
breakList (x:xs) -- (2)
| x == y = (x:ys) : yss -- (3)
| otherwise = [x] : ys : yss -- (4)
where ~(ys#(y:_):yss) = breakList xs -- (5)
here we thus first calculate the result of the tail recursion, we know that this will be non-empty since the (x:xs) pattern in (2) will only fire if the list contains at least two items (if it contains only one item, then the (1) clause will fire.
We then can pattern match the result with the pattern ~(ys#(y:_):yss) where ys is the first sublist of the result, y is the first item of that sublist, and yss is a, possibly empty, list of other groups that have been constructed.
We thus can check if the item x we have to put in a group has the same value as the first item y of the first subgroup. If that is the case we use (x:ys) : yss to construct a new lsit where we prepend the first sublist with x (2); if that is not the case, we prepend the sublists with a list [x] to create a new group.
We can make it more lazy with:
breakList :: Eq a => [a] -> [[a]]
breakList [] = []
breakList [x] = [[x]] -- (1)
breakList (x:xs#(y:_)) -- (2)
| x == y = (x:ys) : yss -- (3)
| otherwise = [x] : ys : yss -- (4)
where ~(ys:yss) = breakList xs -- (5)
This can also work on an infinite list with each time the same object: breakList (1 : 1 : 2 : 4 : 5: 5 : repeat 1)) will produce [[1,1],[2],[4],[5,5],[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, …
Here is an alternative solution which uses a list as auxiliary data structure during the traversal of the list.
This auxiliary data structure stores the equal element up to now. For each new element (1) we check if it is equal to one of the elements in the auxiliary list, if it is we add it to that list, otherwise (2) we output the auxiliary list as a result and start a new auxiliary list with this new element. At the end (3) we simply output the auxiliary list we have got up to now as the final result.
breakList :: [Int] -> [[Int]]
breakList [] = []
breakList (x:xs) = go [x] xs where
go ys [] = [ys] -- (3)
go ~ys#(y:_) (x:xs)
| x == y = go (x:ys) xs -- (1)
| otherwise = ys : go [x] xs -- (2)
If you want it to be stable, i.e. all elements must stay in the same order (in the case of integers this does not matter, but it could for other data types), then you have to reverse the output lists:
breakList :: [Int] -> [[Int]]
breakList [] = []
breakList (x:xs) = go [x] xs where
go ys [] = [reverse ys]
go ~ys#(y:_) (x:xs)
| x == y = go (x:ys) xs
| otherwise = reverse ys : go [x] xs
This algorithm also assumes that == is transitive, which is not technically necessary, but certainly the case for integers. Although, the specification you've given is ambiguous if == is not transitive, which element should we compare each new element to? The first element of the group, or the previous element? Anyway, it is probably not something you have to worry about.
This is what group already does. :) Apparently, it is very unassumingly defined as an equivalent of group (x:xs) = (x:ys) : group zs where (ys,zs) = span (x ==) xs.
Of course you're forbidden the use of HOFs, so will need to inline the definition of span. And it must be lazy enough, i.e. produce as much as possible as early as possible, forcing as little as possible of its input.
Something like
breakList :: [Int] -> [[Int]]
breakList [] = [[]]
breakList (x:ys) = (x:xs):r
where
(xs:r) = go x ys
go x (y:ys)
| x==y = ((y:a):b)
| otherwise = [] : ((y:a):b)
where (a:b) = go y ys
go _ [] = [[]]
So that we have
> breakList $ [1,1,1,2,3,3,4]
[[1,1,1],[2],[3,3],[4]]
> take 1 . head . breakList $ repeat 1
[1]
> take 3 . head . breakList $ [1,1,1]++undefined
[1,1,1]
Seems to be properly lazy indeed.
I'm writing a recursive function that builds a list, but has some conditions where, if met, the function should ignore the list that's been built so far and simply return an empty list on its own.
A simple example:
func (x:xs)
| x < 10 = [x] ++ func xs
| otherwise = ("return an empty list without the already built up list")
So if xs was a list [1 .. 12] then once it's built a list that's [1..9] then when it reaches 10, it'll disregard the list it's built and just return an empty array [], and not return an empty array that's passed back to the already built up list.
Is there a way to do this in Haskell? I've tried doing return [] but it gave me the error:
Couldn't match expected type ‘Int’ with actual type ‘[t0]’
return is not a statement in Haskell, but even if it was it would not work anyway. Since due to recursion, you then return that list at that specific level.
It looks however that you simply want to know if all elements are smaller than 10. If that is the case, you return the entire list, otherwise you return an empty list.
You can do that with:
func :: (Num a, Ord a) => [a] -> [a]
func xs | all (< 10) xs = xs
| otherwise = []
or we can use recursion, and make use of Maybe:
func :: (Num a, Ord a) => [a] -> Maybe [a]
func [] = Just []
func (x:xs) | x < 10 = fmap (x:) (func xs)
| otherwise = Nothing
We can then later convert the Nothing value with fromMaybe :: a -> Maybe a -> a to an empty list, although a Maybe might be better idea here, that allows us to differentatie between func [] and func [14] for example.
I'm new in haskell programming and I try to solve a problem by/not using list comprehensions.
The Problem is to find the index of an element in a list and return a list of the indexes (where the elements in the list was found.)
I already solved the problem by using list comprehensions but now i have some problems to solve the problem without using list comprehensions.
On my recursive way:
I tried to zip a list of [0..(length list)] and the list as it self.
then if the element a equals an element in the list -> make a new list with the first element of the Tupel of the zipped list(my index) and after that search the function on a recursive way until the list is [].
That's my list comprehension (works):
positions :: Eq a => a -> [a] -> [Int]
positions a list = [x | (x,y) <- zip [0..(length list)] list, a == y]
That's my recursive way (not working):
positions' :: Eq a => a -> [a] -> [Int]
positions' _ [] = []
positions' a (x:xs) =
let ((n,m):ns) = zip [0..(length (x:xs))] (x:xs)
in if (a == m) then n:(positions' a xs)
else (positions' a xs)
*sorry I don't know how to highlight words
but ghci says:
*Main> positions' 2 [1,2,3,4,5,6,7,8,8,9,2]
[0,0]
and it should be like that (my list comprehension):
*Main> positions 2 [1,2,3,4,5,6,7,8,8,9,2]
[1,10]
Where is my mistake ?
The problem with your attempt is simply that when you say:
let ((n,m):ns) = zip [0..(length (x:xs))] (x:xs)
then n will always be 0. That's because you are matching (n,m) against the first element of zip [0..(length (x:xs))] (x:xs), which will necessarily always be (0,x).
That's not a problem in itself - but it does mean you have to handle the recursive step properly. The way you have it now, positions _ _, if non-empty, will always have 0 as its first element, because the only way you allow it to find a match is if it's at the head of the list, resulting in an index of 0. That means that your result will always be a list of the correct length, but with all elements 0 - as you're seeing.
The problem isn't with your recursion scheme though, it's to do with the fact that you're not modifying the result to account for the fact that you don't always want 0 added to the front of the result list. Since each recursive call just adds 1 to the index you want to find, all you need to do is map the increment function (+1) over the recursive result:
positions' :: Eq a => a -> [a] -> [Int]
positions' _ [] = []
positions' a (x:xs) =
let ((0,m):ns) = zip [0..(length (x:xs))] (x:xs)
in if (a == m) then 0:(map (+1) (positions' a xs))
else (map (+1) (positions' a xs))
(Note that I've changed your let to be explicit that n will always be 0 - I prefer to be explicit this way but this in itself doesn't change the output.) Since m is always bound to x and ns isn't used at all, we can elide the let, inlining the definition of m:
positions' :: Eq a => a -> [a] -> [Int]
positions' _ [] = []
positions' a (x:xs) =
if a == x
then 0 : map (+1) (positions' a xs)
else map (+1) (positions' a xs)
You could go on to factor out the repeated map (+1) (positions' a xs) if you wanted to.
Incidentally, you didn't need explicit recursion to avoid a list comprehension here. For one, list comprehensions are basically a replacement for uses of map and filter. I was going to write this out explicitly, but I see #WillemVanOnsem has given this as an answer so I will simply refer you to his answer.
Another way, although perhaps not acceptable if you were asked to implement this yourself, would be to just use the built-in elemIndices function, which does exactly what you are trying to implement here.
We can make use of a filter :: (a -> Bool) -> [a] -> [a] and map :: (a -> b) -> [a] -> [b] approach, like:
positions :: Eq a => a -> [a] -> [Int]
positions x = map fst . filter ((x ==) . snd) . zip [0..]
We thus first construct tuples of the form (i, yi), next we filter such that we only retain these tuples for which x == yi, and finally we fetch the first item of these tuples.
For example:
Prelude> positions 'o' "foobaraboof"
[1,2,8,9]
Your
let ((n,m):ns) = zip [0..(length (x:xs))] (x:xs)
is equivalent to
== {- by laziness -}
let ((n,m):ns) = zip [0..] (x:xs)
== {- by definition of zip -}
let ((n,m):ns) = (0,x) : zip [1..] xs
== {- by pattern matching -}
let {(n,m) = (0,x)
; ns = zip [1..] xs }
== {- by pattern matching -}
let { n = 0
; m = x
; ns = zip [1..] xs }
but you never reference ns! So we don't need its binding at all:
positions' a (x:xs) =
let { n = 0 ; m = x } in
if (a == m) then n : (positions' a xs)
else (positions' a xs)
and so, by substitution, you actually have
positions' :: Eq a => a -> [a] -> [Int]
positions' _ [] = []
positions' a (x:xs) =
if (a == x) then 0 : (positions' a xs) -- NB: 0
else (positions' a xs)
And this is why all you ever produce are 0s. But you want to produce the correct index: 0, 1, 2, 3, ....
First, let's tweak your code a little bit further into
positions' :: Eq a => a -> [a] -> [Int]
positions' a = go xs
where
go [] = []
go (x:xs) | a == x = 0 : go xs -- NB: 0
| otherwise = go xs
This is known as a worker/wrapper transform. go is a worker, positions' is a wrapper. There's no need to pass a around from call to call, it doesn't change, and we have access to it anyway. It is in the enclosing scope with respect to the inner function, go. We've also used guards instead of the more verbose and less visually apparent if ... then ... else.
Now we just need to use something -- the correct index value -- instead of 0.
To use it, we must have it first. What is it? It starts as 0, then it is incremented on each step along the input list.
When do we make a step along the input list? At the recursive call:
positions' :: Eq a => a -> [a] -> [Int]
positions' a = go xs 0
where
go [] _ = []
go (x:xs) i | a == x = 0 : go xs (i+1) -- NB: 0
| otherwise = go xs (i+1)
_ as a pattern means we don't care about the argument's value -- it's there but we're not going to use it.
Now all that's left for us to do is to use that i in place of that 0.
What would be the syntax (if possible at all) for returning the list of lists ([[a]]) but without the use of empty list ([]:[a])?
(similar as the second commented guard (2) below, which is incorrect)
This is a function that works correctly:
-- Split string on every (shouldSplit == true)
splitWith :: (Char -> Bool) -> [Char] -> [[Char]]
splitWith shouldSplit list = filter (not.null) -- would like to get rid of filter
(imp' shouldSplit list)
where
imp' _ [] = [[]]
imp' shouldSplit (x:xs)
| shouldSplit x = []:imp' shouldSplit xs -- (1) this line is adding empty lists
-- | shouldSplit x = [imp' shouldSplit xs] -- (2) if this would be correct, no filter needed
| otherwise = let (z:zs) = imp' shouldSplit xs in (x:z):zs
This is the correct result
Prelude> splitWith (== 'a') "miraaaakojajeja234"
["mir","koj","jej","234"]
However, it must use "filter" to clean up its result, so I would like to get rid of function "filter".
This is the result without the use of filter:
["mir","","","","koj","jej","234"]
If "| shouldSplit x = imp' shouldSplit xs" is used instead the first guard, the result is incorrect:
["mirkojjej234"]
The first guard (1) adds empty list so (I assume) compiler can treat the result as a list of lists ([[a]]).
(I'm not interested in another/different solutions of the function, just the syntax clarification.)
.
.
.
ANSWER:
Answer from Dave4420 led me to the answer, but it was a comment, not an answer so I can't accept it as answer. The solution of the problem was that I'm asking the wrong question. It is not the problem of syntax, but of my algorithm.
There are several answers with another/different solutions that solve the empty list problem, but they are not the answer to my question. However, they expanded my view of ways on how things can be done with basic Haskell syntax, and I thank them for it.
Edit:
splitWith :: (Char -> Bool) -> String -> [String]
splitWith p = go False
where
go _ [] = [[]]
go lastEmpty (x:xs)
| p x = if lastEmpty then go True xs else []:go True xs
| otherwise = let (z:zs) = go False xs in (x:z):zs
This one utilizes pattern matching to complete the task of not producing empty interleaving lists in a single traversal:
splitWith :: Eq a => (a -> Bool) -> [a] -> [[a]]
splitWith f list = case splitWith' f list of
[]:result -> result
result -> result
where
splitWith' _ [] = []
splitWith' f (a:[]) = if f a then [] else [[a]]
splitWith' f (a:b:tail) =
let next = splitWith' f (b : tail)
in if f a
then if a == b
then next
else [] : next
else case next of
[] -> [[a]]
nextHead:nextTail -> (a : nextHead) : nextTail
Running it:
main = do
print $ splitWith (== 'a') "miraaaakojajeja234"
print $ splitWith (== 'a') "mirrraaaakkkojjjajeja234"
print $ splitWith (== 'a') "aaabbbaaa"
Produces:
["mir","koj","jej","234"]
["mirrr","kkkojjj","jej","234"]
["bbb"]
The problem is quite naturally expressed as a fold over the list you're splitting. You need to keep track of two pieces of state - the result list, and the current word that is being built up to append to the result list.
I'd probably write a naive version something like this:
splitWith p xs = word:result
where
(result, word) = foldr func ([], []) xs
func x (result, word) = if p x
then (word:result,[])
else (result, x:word)
Note that this also leaves in the empty lists, because it appends the current word to the result whenever it detects a new element that satisfies the predicate p.
To fix that, just replace the list cons operator (:) with a new operator
(~:) :: [a] -> [[a]] -> [[a]]
that only conses one list to another if the original list is non-empty. The rest of the algorithm is unchanged.
splitWith p xs = word ~: result
where
(result, word) = foldr func ([], []) xs
func x (result, word) = if p x
then (word ~: result, [])
else (result, x:word)
x ~: xs = if null x then xs else x:xs
which does what you want.
I guess I had a similar idea to Chris, I think, even if not as elegant:
splitWith shouldSplit list = imp' list [] []
where
imp' [] accum result = result ++ if null accum then [] else [accum]
imp' (x:xs) accum result
| shouldSplit x =
imp' xs [] (result ++ if null accum
then []
else [accum])
| otherwise = imp' xs (accum ++ [x]) result
This is basically just an alternating application of dropWhile and break, isn't it:
splitWith p xs = g xs
where
g xs = let (a,b) = break p (dropWhile p xs)
in if null a then [] else a : g b
You say you aren't interested in other solutions than yours, but other readers might be. It sure is short and seems clear. As you learn, using basic Prelude functions becomes second nature. :)
As to your code, a little bit reworked in non-essential ways (using short suggestive function names, like p for "predicate" and g for a main worker function), it is
splitWith :: (Char -> Bool) -> [Char] -> [[Char]]
splitWith p list = filter (not.null) (g list)
where
g [] = [[]]
g (x:xs)
| p x = [] : g xs
| otherwise = let (z:zs) = g xs
in (x:z):zs
Also, there's no need to pass the predicate as an argument to the worker (as was also mentioned in the comments). Now it is arguably a bit more readable.
Next, with a minimal change it becomes
splitWith :: (Char -> Bool) -> [Char] -> [[Char]]
splitWith p list = case g list of ([]:r)-> r; x->x
where
g [] = [[]]
g (x:xs)
| p x = case z of []-> r; -- start a new word IF not already
_ -> []:r
| otherwise = (x:z):zs
where -- now z,zs are accessible
r#(z:zs) = g xs -- in both cases
which works as you wanted. The top-level case is removing at most one empty word here, which serves as a separator marker at some point during the inner function's work. Your filter (not.null) is essentially fused into the worker function g here, with the conditional opening1 of a new word (i.e. addition1 of an empty list).
Replacing your let with where allowed for the variables (z etc.) to became accessible in both branches of the second clause of the g definition.
In the end, your algorithm was close enough, and the code could be fixed after all.
1 when thinking "right-to-left". In reality the list is constructed left-to-right, in guarded recursion ⁄ tail recursion modulo cons fashion.
I have a problem with a function that should only return the tail of a list. The functions is myTail and should give a useable result, even if the input is an empty list.
I want to understand all 3 ways: pattern matching, guarded equation and conditional expressions
this works:
> myTail_pat :: [a] -> [a]
> myTail_pat (x:xs) = xs
> myTail_pat [] = []
But this:
> myTail_guard (x:xs) | null xs = []
> | otherwise = xs
gives me the error: Program error: pattern match failure: myTail_guard []
How can i declare the function without patterns?
Thank you.
The pattern x:xs does not match the empty list. You'd need to do:
myTail_guard xs
| null xs = []
| otherwise = tail xs
drop 1 is safe
drop 1 []
-- result: []