Haskell Filtering but keeping the filtered - haskell

In my understanding, the Haskell filter function filter a bs would filter all a's from a list bs.
Is there a simple method or variation of filter that would do the opposite, only keeping the a's from the list bs, basically creating a list of a's.

Well, that's imprecise wording anyway. The signature is
filter :: (a -> Bool) -> [a] -> [a]
so filter a bs is described as filter all elements from bs that fulfill a.
So to "do the opposite", you just need to invert the predicate. For instance,
Prelude> filter (== 'a') "Is there a simple method or variation of filter that"
"aaaa"
Prelude> filter (/= 'a') "Is there a simple method or variation of filter that"
"Is thereĀ  simple method or vrition of filter tht"
In general:
filterNot :: (a -> Bool) -> [a] -> [a]
filterNot pred = filter $ not . pred
Prelude> filterNot (== 'a') "Is there a simple method or variation of filter that"
"Is thereĀ  simple method or vrition of filter tht"

remove f = filter (not . f)
> remove odd [1..10]
[2,4,6,8,10]

The filter function takes a predicate function of the type a -> Bool and a list of type [a], and it applies the predicate to each element of the list to determine if it should be kept. As an example, you could do filter (\x -> x < 2 || x > 10) someNumbers, which would return a list of all the values from someNumbers that are either less than 2 or greater than 10.
If you wanted all of a particular element from a list, you could do
only :: Eq a => a -> [a] -> [a]
only x xs = filter (== x) xs
Since the predicate is then checking if each element is equal to a particular one.

filter :: (a -> Bool) -> [a] -> [a]
> filter (<5) [1 .. 10]
[1,2,3,4]
It filter some elements which saisfy some condition
The opposite function is the same function with negative boolean condition
filterNot f = filter (not . f)
> filterNot (<5) [1 .. 10]
[5,6,7,8,9,10]

Or, what lead me to this page, a way to keep both a's and b's, but separated:
> foldl (\(evens,odds) e -> if e `mod` 2 == 0 then (e:evens, odds) else (evens, e:odds)) ([],[]) (reverse [1..10])
([2,4,6,8,10],[1,3,5,7,9])

Related

How can I add something to a list when a condition is true and do nothing otherwise in Haskell?

I was hoping to find a better way to solve a problem I've encountered in Haskell.
Given a list and a condition create a new list with only elements which satisfy the condition. Below is a solution I used. Is there a better alternative which doesn't involve maybes?
eg :: (Eq a, Num a) => (a -> Bool) -> [a] -> [a]
eg cond i = catMaybes (map (\x-> if cond x then Just x else Nothing) i)
Your eg is equivalent to filter :: (a -> Bool) -> [a] -> [a]. Indeed, you can filter with:
filter (\x -> some_condition x) my_list
If some_condition is for example a simple a -> Bool function, this is equivalent to:
filter some_condition my_list
Neither your implementation of eg nor the one with filter require the Eq a and Num a type constraints by the way: one can simply use guards or pattern match on the outcome of cond x.
filter is implemented with explicit recursion [src]:
filter :: (a -> Bool) -> [a] -> [a]
filter _pred [] = []
filter pred (x:xs)
| pred x = x : filter pred xs
| otherwise = filter pred xs
Here for an empty list it thus returns the empty list, and when the list is not empty, it will only prepend x if pred x is satisfied.

Taking the rest of the list into account in filter

I need to display the number of elements whose successor is greater in a list. For example, in the list [3,7,2,1,9] my function should return 2 because 7 is greater than 3 and 9 is greater than 1.
In order to do that,I was thinking to use the filter function:
greaterElems :: Ord a => [a] -> Int
greaterElems [] = 0
greaterElems [x] = 0
greaterElems (x:xs) = length (filter (< head xs) (x:xs))
However, this does not work as expected: it seems that Haskell always considers the second element of the list, as if "head xs" is calculated only once, but this does not seem normal to me since Haskell is lazy.
What am I missing and how could I fix my code in order to achieve my goal?
You can make use of zipWith :: (a -> b -> c) -> [a] -> [b] -> [c] where we pass the list, and its tail. Indeed:
sucGreater :: Ord a => [a] -> [Bool]
sucGreater x = zipWith (<) x (tail x)
or as #RobinZigmond says, we can omit tail, and use drop:
sucGreater :: Ord a => [a] -> [Bool]
sucGreater x = zipWith (<) x (drop 1 x)
For the given sample list, this gives us:
Prelude> sucGreater [3,7,2,1,9]
[True,False,False,True]
I leave it as an exercise to the count the number of Trues in that list.

Is there a straight-forward solution to receiving the element *prior* to hitting the dropWhile predicate?

Given a condition, I want to search through a list of elements and return the first element that reaches the condition, and the previous one.
In C/C++ this is easy :
int i = 0;
for(;;i++) if (arr[i] == 0) break;
After we get the index where the condition is met, getting the previous element is easy, through "arr[i-1]"
In Haskell:
dropWhile (/=0) list gives us the last element I want
takeWhile (/=0) list gives us the first element I want
But I don't see a way of getting both in a simple manner. I could enumerate the list and use indexing, but that seems messy. Is there a proper way of doing this, or a way of working around this?
I would zip the list with its tail so that you have pairs of elements
available. Then you can just use find on the list of pairs:
f :: [Int] -> Maybe (Int, Int)
f xs = find ((>3) . snd) (zip xs (tail xs))
> f [1..10]
Just (3,4)
If the first element matches the predicate this will return
Nothing (or the second match if there is one) so you might need to special-case that if you want something
different.
As Robin Zigmond says break can also work:
g :: [Int] -> (Int, Int)
g xs = case break (>3) xs of (_, []) -> error "not found"
([], _) -> error "first element"
(ys, z:_) -> (last ys, z)
(Or have this return a Maybe as well, depending on what you need.)
But this will, I think, keep the whole prefix ys in memory until it
finds the match, whereas f can start garbage-collecting the elements
it has moved past. For small lists it doesn't matter.
I would use a zipper-like search:
type ZipperList a = ([a], [a])
toZipperList :: [a] -> ZipperList a
toZipperList = (,) []
moveUntil' :: (a -> Bool) -> ZipperList a -> ZipperList a
moveUntil' _ (xs, []) = (xs, [])
moveUntil' f (xs, (y:ys))
| f y = (xs, (y:ys))
| otherwise = moveUntil' f (y:xs, ys)
moveUntil :: (a -> Bool) -> [a] -> ZipperList a
moveUntil f = moveUntil' f . toZipperList
example :: [Int]
example = [2,3,5,7,11,13,17,19]
result :: ZipperList Int
result = moveUntil (>10) example -- ([7,5,3,2], [11,13,17,19])
The good thing about zippers is that they are efficient, you can access as many elements near the index you want, and you can move the focus of the zipper forwards and backwards. Learn more about zippers here:
http://learnyouahaskell.com/zippers
Note that my moveUntil function is like break from the Prelude but the initial part of the list is reversed. Hence you can simply get the head of both lists.
A non-awkward way of implementing this as a fold is making it a paramorphism. For general explanatory notes, see this answer by dfeuer (I took foldrWithTails from it):
-- The extra [a] argument f takes with respect to foldr
-- is the tail of the list at each step of the fold.
foldrWithTails :: (a -> [a] -> b -> b) -> b -> [a] -> b
foldrWithTails f n = go
where
go (a : as) = f a as (go as)
go [] = n
boundary :: (a -> Bool) -> [a] -> Maybe (a, a)
boundary p = foldrWithTails findBoundary Nothing
where
findBoundary x (y : _) bnd
| p y = Just (x, y)
| otherwise = bnd
findBoundary _ [] _ = Nothing
Notes:
If p y is true we don't have to look at bnd to get the result. That makes the solution adequately lazy. You can check that by trying out boundary (> 1000000) [0..] in GHCi.
This solution gives no special treatment to the edge case of the first element of the list matching the condition. For instance:
GHCi> boundary (<1) [0..9]
Nothing
GHCi> boundary even [0..9]
Just (1,2)
There's several alternatives; either way, you'll have to implement this yourself. You could use explicit recursion:
getLastAndFirst :: (a -> Bool) -> [a] -> Maybe (a, a)
getLastAndFirst p (x : xs#(y:ys))
| p y = Just (x, y)
| otherwise = getLastAndFirst p xs
getLastAndFirst _ [] = Nothing
Alternately, you could use a fold, but that would look fairly similar to the above, except less readable.
A third option is to use break, as suggested in the comments:
getLastAndFirst' :: (a -> Bool) -> [a] -> Maybe (a,a)
getLastAndFirst' p l =
case break p l of
(xs#(_:_), (y:_)) -> Just (last xs, y)
_ -> Nothing
(\(xs, ys) -> [last xs, head ys]) $ break (==0) list
Using break as Robin Zigmond suggested ended up short and simple, not using Maybe to catch edge-cases, but I could replace the lambda with a simple function that used Maybe.
I toyed a bit more with the solution and came up with
breakAround :: Int -> Int -> (a -> Bool) -> [a] -> [a]
breakAround m n cond list = (\(xs, ys) -> (reverse (reverse take m (reverse xs))) ++ take n ys) $ break (cond) list
which takes two integers, a predicate, and a list of a, and returns a single list of m elements before the predicate and n elements after.
Example: breakAround 3 2 (==0) [3,2,1,0,10,20,30] would return [3,2,1,0,10]

Apply a function to every element in a list to every element in another list - Haskell

My ultimate goal is to find if a list y contains all the elements of list x (I'm checking if x is a subset of y sort of thing)
subset x y =
and [out | z <- x
, out <- filter (==z) y ]
This doesn't work, and I know it's because z is a list still. I'm trying to make sense of this.
I think I may have to use the elem function, but I'm not sure how to split x into chars that I can compare separately through y.
I'm ashamed to say that I've been working on this simple problem for an hour and a half.
Checking whether all elements of xs are elements of ys is very straightforward. Loop through xs, and for each element, check if it is in ys:
subset xs ys = all (\x -> elem x ys) xs
You could also use the list difference function (\\). If you have list y and list x, and you want to check that all elements of x are in y, then x \\ y will return a new list with the elements of x that are not in y. If all the elements of x are in y, the returned list will be empty.
For example, if your list y is [1,2,3,4,5] and your list x is [2,4], you can do:
Prelude> [2,4] \\ [1,2,3,4,5]
[]
If list y is [1,2,3,4,5] and list x is [2,4,6], then:
Prelude> [2,4,6] \\ [1,2,3,4,5]
[6]
Easy way to reason about subsets is to use sets as the data type.
import qualified Data.Set as S
subset :: Ord a => [a] -> [a] -> Bool
subset xs ys = S.isSubsetOf (S.fromList xs) (S.fromList ys)
Then it's as simple as:
*Main> subset [1..5] [1..10]
True
*Main> subset [0..5] [1..10]
False
Let's break this down into two subproblems:
Find if a value is a member of a list;
Use the solution to #1 to test whether every value in a list is in the second one.
For the first subproblem there is a library function already:
elem :: (Eq a, Foldable t) => a -> t a -> Bool
Lists are a Foldable type, so you can use this function with lists for t and it would have the following type:
elem :: (Eq a) => a -> [a] -> Bool
EXERCISE: Write your own version of elem, specialized to work with lists (don't worry about the Foldable stuff now).
So now, to tackle #2, one first step would be this:
-- For each element of `xs`, test whether it's an element of `ys`.
-- Return a list of the results.
notYetSubset :: Eq a => [a] -> [a] -> [Bool]
notYetSubset xs ys = map (\x -> elem x ys) xs
After that, we need to go from the list of individual boolean results to just one boolean. There's a standard library function that does that as well:
-- Return true if and only if every element of the argument collection is
-- is true.
and :: Foldable t => t Bool -> Bool
EXERCISE: write your own version of and, specialized to lists:
myAnd :: [Bool] -> Bool
myAnd [] = _fillMeIn
myAnd (x:xs) = _fillMeIn
With these tools, now we can write subset:
subset :: Eq a => [a] -> [a] -> [Bool]
subset xs ys = and (map (\x -> elem x ys) xs)
Although a more experienced Haskeller would probably write it like this:
subset :: Eq a => [a] -> [a] -> [Bool]
subset xs ys = every (`elem` ys) xs
{- This:
(`elem` ys)
...is a syntactic shortcut for this:
\x -> x elem ys
-}
...where every is another standard library function that is just a shortcut for the combination of map and and:
-- Apply a boolean test to every element of the list, and
-- return `True` if and only if the test succeeds for all elements.
every :: (a -> Bool) -> [a] -> Bool
every p = and . map p

Compute the mode of a list

Now I am going to compute the most common item in a list.
I did it step by step.
sort the list
group the list
count how many times of every number
I don't know how to continue...please help. This is the code I have
done now
group :: Eq a => [a] -> [[a]]
group = groupBy (==)
-- | The 'groupBy' function is the non-overloaded version of 'group'.
groupBy :: (a -> a -> Bool) -> [a] -> [[a]]
groupBy _ [] = []
groupBy eq (x:xs) = (x:ys) : groupBy eq zs
where (ys,zs) = span (eq x) xs
task4 xs = (map (\l#(x:xs) -> (x,length l)) (group (sortList xs)))
<main> task4 [1,1,1,2,2,3]
[(1,3),(2,2),(3,1)]
Let's first assume you're only interested in how often the mode turns up. So you'd just use
map length . group $ sortList xs
giving you a list of lengths of the individual groups. Then what's left to do is retrieve the maximum.
Now, that's not all you want. Basically, you want the maximum of your tuple list, but it should compare only the length field, not the element one. You might thus be temped to hoogle for Ord b => [(a, b)] -> a (or -> (a,b)), but there is no such standard function.
However, as you've already searched for maximum and a special form of this is just what you want, you can scroll down that result page, and you'll find maximumBy. It allows you to specify which "property" should be considered for comparison.
The preferred way to use this is the rather self-explanatory
GHCi> :m +Data.Ord Data.List
GHCi> :t maximumBy (comparing snd)
maximumBy (comparing snd) :: Ord a => [(a1, a)] -> (a1, a)
So we're handling the information of how to access the crucial field as an argument to the function. Well, but as snd is itself a function, we can as well use any other one! So there's no real need to build up the elem+runlength tuples in the first place, you might as well just do
maximumBy (comparing length) . group $ sort xs
which gives the proper result (though that's a bit less efficient). In short:
mode :: Ord a => [a] -> a
mode = maximumBy (comparing length) . group . sort
You're very close. If instead of:
(\l#(x:xs) -> (x,length l))
you wrote:
(\l#(x:xs) -> (length l,x))
then you could simply take maximum of your output:
maximum [(3,1),(2,2),(1,3)] == (3,1)

Resources