Haskell idiom for 'selective' map - haskell

Suppose one wants to map over a collection, but only collect results of the mapped function if the mapped-upon value meets certain criteria. I am currently doing this as such:
func = foldl (\acc x, -> (maybeGrab x):acc) []
maybeGrab a
| a > 5 = [someFunc a]
| otherwise = []
While this works, I am sure there is a more idiomatic 'right/common/more recognisable' way to do this.

mapMaybe :: (a -> Maybe b) -> [a] -> [b]
mapMaybe from the Data.Maybe package looks like it does the job. The documentation says:
The mapMaybe function is a version of map which can throw out elements. In particular, the functional argument returns something of type Maybe b. If this is Nothing, no element is added on to the result list. If it just Just b, then b is included in the result list.

Personally, I would do this in two stages: first, eliminate the values you don't care about, then map.
func = map someFunc . filter (>5)
This can also be expressed nicely as a list comprehension.
func xs = [someFunc x | x <- xs, x > 5]

Hmm. This definitely seems like a place where a fold is just fine. What about:
func = foldl (\acc x -> let a = g x in if a > 5 then a:acc else acc) []
Here g is the function you are trying to map over the list.
I can't think of any function that natively combines map and filter without folding.
[EDIT]
Oh, apparently there is a mapMaybe. Never used that before. I stand corrected. Ha, learn something all the time.

Related

Haskell's span function

I'm relatively new to Haskell and I'm struggling to figure out a way to implement Haskell's span function. However, my problem is more general than that in that I don't know how to make a function return a list of lists or list of tuples containing the elements I want. My problem with a list of lists such as:
[[1],[2]]
is that I can't make the function add an element to the first list in the list of lists. I only know how to append another list to the list of lists.
In short, if you explain to me how to implement the span function, this all should hopefully come clear to me.
So I think what you're saying is that you know how to recursively append to a list by doing something like
foobar :: [x] -> [y]
foobar ( []) = []
foobar (x:xs) = {- ...stuff... -} : foobar xs
but you have no idea how to do that with two lists:
foobar :: [x] -> ([y], [z])
foobar (x:xs) = ???
In general, when the result isn't a list, but something that contains a list, you end up doing something like this:
foobar :: [x] -> ([y], [z])
foobar (x:xs) =
let
y = {- whatever -}
z = {- whatever -}
(ys, zs) = foobar xs -- The recursive call
in (y:ys, z:zs)
The same applies if, say, the result is a monadic action
foobar :: [x] -> IO [y]
foobar (x:xs) = do
y <- {- whatever -}
ys <- foobar xs
return (y:ys)
Note that this forces the function to not be lazy.
The general pattern I think you'll want to use here is the following:
span :: (a -> Bool) -> [a] -> ([a], [a])
span pred [] = ([], [])
span pred (x:xs) = if pred x then _ else _ -- fill in the blanks
where (prefix', suffix') = span pred xs
There are two non-obvious things there. First, note the pattern match in the where condition. This means that we're:
Calling span pred xs, which produces a pair of lists;
Pattern matching on this pair;
Naming the first and second element of the pair prefix' and suffix' respectively.
I suspect that step #2, the pattern match on the result of the recursive call, is something you might not have understood.
The second non-obvious thing is recursion. It's a tricky thing because, counterintutively, to solve a problem with recursion you need to assume that you've already solved it, but for the "wrong" argument--a tough step to picture yourself taking if you haven't solved it yet! But the trick is this:
Imagine you've actually already solved the problem, but for the tail of the list. That's what the prefix' and suffix' variables contain: a correct solution but for the wrong list--the tail of the one you're actually trying to solve for.
Given that (non)solution, how could you reuse it to arrive at a correct solution for your problem?

Little problems from a Haskell learner about filter & fold

This is my second day learning Haskell and I am stuck terribly by a problem.
I tried to solve the eighth problem in 99 Haskell questions
The problem is to write a function called "compress" which works like this:
>compress "aaaabbbbccccddddd"
"abcd"
>compress [1,1,1,1,2,3,4,4,4,4]
[1,2,3,4]
and here's what I wrote:
compress :: (Eq a) => [a] -> [a]
compress [] = []
compress x = filter ( (head x) `notElem` ( compress $ tail x ) ) x
The compiler said:
Couldn't match expected type a -> Bool' with actual type Bool'
In compress, I tried to recursively pick up new elements from end to head. (like backtracking maybe??)
Is my algorithm wrong?
Is there alternative way to implement the algorithm in a more readable way?
(Like: where to put parentheses? or $ )
Can someone kindly help me with it?
Thanks a lot.
Thanks to Lubomir's help, I corrected my code by :
compress'(x:xs) = x : compress' (dropWhile (== x) xs)
and it works!
And thanks everyone, I feel spoiled! You guys are so kind!
I'll keep on learning Haskell!
Is there alternative way to implement the algorithm in a more readable
way?
Yes.
import Data.List
compress :: Eq a => [a] -> [a]
compress = map head . group
map head . group is basically \xs -> map head (group xs). group xs will create a list of lists were all equal consecutive elements are grouped together in a list. map head will then take the heads of these lists discarding the rest as required.
The algorithm is basically fine, but it does not typecheck. The first argument to filter should be a function of type a -> Bool – for an element of the list it should tell you whether or not to throw it out. What you have is a single Bool value.
The second part of the function may be better implemented with a different pattern. This would allow you to drop the head and tail functions.
compress [] = []
compress (x:xs) = x : compress (filter (/= x) xs)
This pattern binds x to the first element of the list and xs is the tail of the list. The function should include x in the result and recursively call itself on filtered xs (with x removed from it).
EDIT: this function does not do what the problem requests. Only consecutive duplicates should be eliminated. This can be fixed by using dropWhile instead of filter and slightly modifying the predicate function.
Check the signature of filter:
Prelude> :t filter
filter :: (a -> Bool) -> [a] -> [a]
Note that the first argument must be a function. Now check the type of your expression within the paranthesis.
Prelude> :t notElem
notElem :: Eq a => a -> [a] -> Bool
Thus, notElem a b will return a value of type Bool.
Note: I think you might have misunderstood the problem statement. What is the expected output for aaabbbaaa?
I would argue it should be aba, as the problem is stated as
Eliminate consecutive duplicates of list elements.
(emphasize mine).

Compute Most Frequent Occurance of Numbers of A Sorted List in Haskell

The question is to compute the mode (the value that occurs most frequently) of a sorted list of integers.
[1,1,1,1,2,2,3,3] -> 1
[2,2,3,3,3,3,4,4,8,8,8,8] -> 3 or 8
[3,3,3,3,4,4,5,5,6,6] -> 3
Just use the Prelude library.
Are the functions filter, map, foldr in Prelude library?
Starting from the beginning.
You want to make a pass through a sequence and get the maximum frequency of an integer.
This sounds like a job for fold, as fold goes through a sequence aggregating a value along the way before giving you a final result.
foldl :: (a -> b -> a) -> a -> [b] -> a
The type of foldl is shown above. We can fill in some of that already (I find that helps me work out what types I need)
foldl :: (a -> Int -> a) -> a -> [Int] -> a
We need to fold something through that to get the value. We have to keep track of the current run and the current count
data BestRun = BestRun {
currentNum :: Int,
occurrences :: Int,
bestNum :: Int,
bestOccurrences :: Int
}
So now we can fill in a bit more:
foldl :: (BestRun -> Int -> BestRun) -> BestRun -> [Int] -> BestRun
So we want a function that does the aggregation
f :: BestRun -> Int -> BestRun
f (BestRun current occ best bestOcc) x
| x == current = (BestRun current (occ + 1) best bestOcc) -- continuing current sequence
| occ > bestOcc = (BestRun x 1 current occ) -- a new best sequence
| otherwise = (BestRun x 1 best bestOcc) -- new sequence
So now we can write the function using foldl as
bestRun :: [Int] -> Int
bestRun xs = bestNum (foldl f (BestRun 0 0 0 0) xs)
Are the functions filter, map, foldr in Prelude library?
Stop...Hoogle time!
Did you know Hoogle tells you which module a function is from? Hoolging map results in this information on the search page:
map :: (a -> b) -> [a] -> [b]
base Prelude, base Data.List
This means map is defined both in Prelude and in Data.List. You can hoogle the other functions and likewise see that they are indeed in Prelude.
You can also look at Haskell 2010 > Standard Prelude or the Prelude hackage docs.
So we are allowed to map, filter, and foldr, as well as anything else in Prelude. That's good. Let's start with Landei's idea, to turn the list into a list of lists.
groupSorted :: [a] -> [[a]]
groupSorted = undefined
-- groupSorted [1,1,2,2,3,3] ==> [[1,1],[2,2],[3,3]]
How are we supposed to implement groupSorted? Well, I dunno. Let's think about that later. Pretend that we've implemented it. How would we use it to get the correct solution? I'm assuming it is OK to choose just one correct solution, in the event that there is more than one (as in your second example).
mode :: [a] -> a
mode xs = doSomething (groupSorted xs)
where doSomething :: [[a]] -> a
doSomething = undefined
-- doSomething [[1],[2],[3,3]] ==> 3
-- mode [1,2,3,3] ==> 3
We need to do something after we use groupSorted on the list. But what? Well...we should find the longest list in the list of lists. Right? That would tell us which element appears the most in the original list. Then, once we find the longest sublist, we want to return the element inside it.
chooseLongest :: [[a]] -> a
chooseLongest xs = head $ chooseBy (\ys -> length ys) xs
where chooseBy :: ([a] -> b) -> [[a]] -> a
chooseBy f zs = undefined
-- chooseBy length [[1],[2],[3,3]] ==> [3,3]
-- chooseLongest [[1],[2],[3,3]] ==> 3
chooseLongest is the doSomething from before. The idea is that we want to choose the best list in the list of lists xs, and then take one of its elements (its head does just fine). I defined this by creating a more general function, chooseBy, which uses a function (in this case, we use the length function) to determine which choice is best.
Now we're at the "hard" part. Folds. chooseBy and groupSorted are both folds. I'll step you through groupSorted, and leave chooseBy up to you.
How to write your own folds
We know groupSorted is a fold, because it consumes the entire list, and produces something entirely new.
groupSorted :: [Int] -> [[Int]]
groupSorted xs = foldr step start xs
where step :: Int -> [[Int]] -> [[Int]]
step = undefined
start :: [[Int]]
start = undefined
We need to choose an initial value, start, and a stepping function step. We know their types because the type of foldr is (a -> b -> b) -> b -> [a] -> b, and in this case, a is Int (because xs is [Int], which lines up with [a]), and the b we want to end up with is [[Int]].
Now remember, the stepping function will inspect the elements of the list, one by one, and use step to fuse them into an accumulator. I will call the currently inspected element v, and the accumulator acc.
step v acc = undefined
Remember, in theory, foldr works its way from right to left. So suppose we have the list [1,2,3,3]. Let's step through the algorithm, starting with the rightmost 3 and working our way left.
step 3 start = [[3]]
Whatever start is, when we combine it with 3 it should end up as [[3]]. We know this because if the original input list to groupSorted were simply [3], then we would want [[3]] as a result. However, it isn't just [3]. Let's pretend now that it's just [3,3]. [[3]] is the new accumulator, and the result we would want is [[3,3]].
step 3 [[3]] = [[3,3]]
What should we do with these inputs? Well, we should tack the 3 onto that inner list. But what about the next step?
step 2 [[3,3]] = [[2],[3,3]]
In this case, we should create a new list with 2 in it.
step 1 [[2],[3,3]] = [[1],[2],[3,3]]
Just like last time, in this case we should create a new list with 1 inside of it.
At this point we have traversed the entire input list, and have our final result. So how do we define step? There appear to be two cases, depending on a comparison between v and acc.
step v acc#((x:xs):xss) | v == x = (v:x:xs) : xss
| otherwise = [v] : acc
In one case, v is the same as the head of the first sublist in acc. In that case we prepend v to that same sublist. But if such is not the case, then we put v in its own list and prepend that to acc. So what should start be? Well, it needs special treatment; let's just use [] and add a special pattern match for it.
step elem [] = [[elem]]
start = []
And there you have it. All you have to do to write your on fold is determine what start and step are, and you're done. With some cleanup and eta reduction:
groupSorted = foldr step []
where step v [] = [[v]]
step v acc#((x:xs):xss)
| v == x = (v:x:xs) : xss
| otherwise = [v] : acc
This may not be the most efficient solution, but it works, and if you later need to optimize, you at least have an idea of how this function works.
I don't want to spoil all the fun, but a group function would be helpful. Unfortunately it is defined in Data.List, so you need to write your own. One possible way would be:
-- corrected version, see comments
grp [] = []
grp (x:xs) = let a = takeWhile (==x) xs
b = dropWhile (==x) xs
in (x : a) : grp b
E.g. grp [1,1,2,2,3,3,3] gives [[1,1],[2,2],[3,3,3]]. I think from there you can find the solution yourself.
I'd try the following:
mostFrequent = snd . foldl1 max . map mark . group
where
mark (a:as) = (1 + length as, a)
mark [] = error "cannot happen" -- because made by group
Note that it works for any finite list that contains orderable elements, not just integers.

Write a function using recursion or higher order functions

How to write a function that takes a predicate f and a list xx and reutrns true if fx is true for some x∈xs?
For example:
ghci>exists (>2) [1,2,3]
True
This is the function I wrote:
exists :: (t->Bool)->[t]->Bool
exists f a []=error
exists f a (x:xs)
|if x∈f a =True
|otherwise= x:f a xs
I know this is not right, but I don't know why. Do I need to write this predicate function f first, then used it inside the function exists. Because I really don't know how to compare one element of list xs with the function.
Your desired example usage is this
ghci>exists (>2) [1,2,3]
True
Stop. Hoogle time. ( <------ This should be the Haskell motto imho)
You want a function ("exists") that takes two parameters. The first is a unary function (a -> Bool) and the second is a list [a]. The desired result is a Bool
Hoogling that type signature, (a -> Bool) -> [a] -> Bool, the top hits are any, all, and find. As Andrew has noted, any is the one that behaves like the "exists" function.
As a side note, my first thought was to use find, which returns a Maybe a, and then pattern match. If it returns Nothing, then the result would be False, otherwise True.
As another side note, the actual implementation is simply any p = or . map p.
The third side note is probably the answer to your actual question. How is map defined? Hoogle is once again your friend. Search for the method's name and you can find a page that links to the source. I suggest you do this for map and or, but will only show map here.
map _ [] = []
map f (x:xs) = f x : map f xs
That's the basic way to recurse over a list. recursiveCall f (x:xs) = f x : recursiveCall f xs But if it can be written with map, filter, or foldl/foldr, then you should do it with these recursive methods. (Stop. Hoogle time. Search for those method names and check out the source; it's pretty straightforward.)
If we take a look at your definition,
exists :: (t -> Bool) -> [t] -> Bool
exists f a []=error
exists f a (x:xs)
|if x∈f a =True
|otherwise= x:f a xs
We see that your type is
exists :: (t -> Bool) -> [t] -> Bool
So exists must take two parameters, one predicate function of type (t -> Bool) and one list of type [t]. It returns a Bool. This seem okay as per our intention of the specification.
Let us look at the first line of your terms:
exists f a [] = error
This function suddenly takes three parameters. The f and the empty list constructor [] looks okay, but the a is not mentioned in the type specification. Hence, we prune it out:
exists f [] = error
Now, the error returned is not of boolean value. But the spec says it must be. Let us suppose we are asking exists (<2) []. Then would a natural answer to the question be True or False? Or paraphrased, is there any element x in [] satisfying the predicate f x ?
On to the next line,
exists f a (x:xs)
|if x∈f a =True
|otherwise= x:f a xs
We learned that the a has to go by the type specification, so let us prune it. Since we have now grown a natural dislike for the a, why not prune it everywhere it occur. Also, since the if will produce a syntax error, lets rid ourselves of that too:
exists f (x:xs)
| x∈f = True
| otherwise = x:f xs
The x∈f does not make much sense, but f x does. The guard variant will be taken if f x returns true. Now, the True which is returned here sounds about right. It signifies that we have found an element in the list matching the predicate - and lo n' behold, x might be it!
So we turn our attention to the final line. The otherwise means that the guard f x did not return True. As a consequence, the x is not satisfying the predicate, so we must search the rest of the list.
The Right-hand-side x : f xs is peculiar. The : means that we will try to return a list, but the return type of the function is something of type Bool. The type checker won't like us if we try this. Furthermore, we have no reason to look at the x anymore since we just determined it does not satisfy the predicate.
The key thing you are missing is that we need recursion at this point. We need to search the tail xs of the list somehow - and recursion means to invoke the exists function on the tail.
Your general track is right, but ask again if something is unclear. One trick might be to go by the types for the recursion case: "What do i have to supply exists for it to return a Bool value?".
I think the function you want already exists -- any:
Prelude> :t any
any :: (a -> Bool) -> [a] -> Bool
Prelude> any (<3) [1, 2, 3, 4]
True
Prelude> any (<3) [3, 4, 5, 6]
False
And then, in the spirit of your question -- not just getting a working function but working out how it's done -- we can look up the definition in the prelude:
any p xs = or (map p xs)
We map the function over the list to get a new [Bool] list, and then check with or to see if any of them are True, which by the way thanks to lazy evaluation short circuits as needed:
Prelude> any (<3) [1, 2..]
True
Actually your original version wasn't too far from working. To fix it, write:
exists :: (t -> Bool) -> [t] -> Bool
exists _ [] = False
exists f (x:xs)
| f x = True
| otherwise = exists f xs
Instead of using x in f, just apply f to x using f x as the predicate in the if statement. Your otherwise clause should also return a Bool: the result of exists on the rest of the list.

When destructuring tuples in Haskell, where can the elements be used?

I am reading a tutorial that uses the following example (that I'll generalize somewhat):
f :: Foo -> (Int, Foo)
...
fList :: Foo -> [Int]
fList foo = x : fList bar
where
(x, bar) = f foo
My question lies in the fact that it seems you can refer to x and bar, by name, outside of the tuple where they are obtained. This would seem to act like destructuring parameter lists in other languages, if my guess is correct. (In other words, I didn't have to do the following:)
fList foo = (fst tuple) : fList (snd tuple)
where
tuple = f foo
Am I right about this behavior? I've never seen it mentioned yet in the tutorials/books I've been reading. Can someone point me to more info on the subject?
Edit: Can anything (lists, arrays, etc.) be destructured in a similar way, or can you only do this with tuples?
Seeing your edit, I think what your asking about is Pattern matching.
And to answer your question: Yes, anything you can construct, you can also 'deconstruct' using the constructors. For example, you're probably familiar with this form of pattern matching:
head :: [a] -> a
head (x:xs) = x
head [] = error "Can't take head of empty list"
However, there are more places where you can use pattern matching, other valid notations are:
head xs = case xs of
(y:ys) -> y
[] -> error "Can't take head of empty list"
head xs = let (y:ys) = xs
in y
head xs = y
where
(y:ys) = xs
Note that the last two examples are a bit different from the first to because they give different error messages when you call them with an empty list.
Although these examples are specific to lists, you can do the same with other data types, like so:
first :: (a, b) -> a
first tuple = x
where
(x, y) = tuple
second :: (a, b) -> b
second tuple = let (x, y) = tuple
in y
fromJust :: Maybe a -> a
fromJust ma = x
where
(Just x) = ma
Again, the last function will also crash if you call it with Nothing.
To sum up; if you can create something using constructors (like (:) and [] for lists, or (,) for tuples, or Nothing and Just for Maybe), you can use those same constructors to do pattern matching in a variety of ways.
Am I right about this behavior?
Yes. The names exist only in the block where you have defined them, though. In your case, this means the logical unit that your where clause is applied to, i.e. the expression inside fList.
Another way to look at it is that code like this
x where x = 3
is roughly equivalent to
let x = 3 in x
Yes, you're right. Names bound in a where clause are visible to the full declaration preceding the where clause. In your case those names are f and bar.
(One of the hard things about learning Haskell is that it is not just permitted but common to use variables in the source code in locations that precede the locations where those variables are defined.)
The place to read more about where clauses is in the Haskell 98 Report or in one of the many fine tutorials to be found at haskell.org.

Resources