How do I split a list of tuples into two lists in haskell using the map function? - haskell

This is for homework due yesterday but I do not want the answer just a point to the right direction please;)
I am trying to implement the unzip function using map and lambda with haskell.
:t unzip
[(a,b)] -> ([a],[b])
and so I am thinking that the lambda would look like \(a,b)->([a],[b]) and that sort of works except I am getting from my input of [(4,5),(7,5),(9,7)] =>
[([4],[5]),([7],[5]),([9],[7])] but I would have liked to have seen [4,7,9],[5,5,7]. So what am I doing wrong here?
Thanks in advance for pointing me in the right direction

Well, map :: (a -> b) -> ([a] -> [b]) returns a list, right? And you want your function to return two lists, so... you'll need to use map twice. Here's a skeleton for you to fill in:
unzip xs = (map {- ??? -} xs, map {- ??? -} xs)
Unfortunately, insisting on using map is inefficient, because it means you must make two passes over the list. You can do a bit better, but it's tricky! Give it a shot, then see how well you did by comparing it with GHC's implementation.

you can not implement unzip in a single map
\(a,b)->([a],[b]) :: (a,b) -> ([a],[b])
so
map \(a,b)->([a],[b]) :: [(a,b)] -> [([a],[b])]
instead you need two maps
unzip ls = (map ???,map ???)
fill in the blanks

Related

Maybe monad and a list

Ok, so I am trying to learn how to use monads, starting out with maybe. I've come up with an example that I can't figure out how to apply it to in a nice way, so I was hoping someone else could:
I have a list containing a bunch of values. Depending on these values, my function should return the list itself, or a Nothing. In other words, I want to do a sort of filter, but with the consequence of a hit being the function failing.
The only way I can think of is to use a filter, then comparing the size of the list I get back to zero. Is there a better way?
This looks like a good fit for traverse:
traverse :: (Traversable t, Applicative f) => (a -> f b) -> t a -> f (t b)
That's a bit of a mouthful, so let's specialise it to your use case, with lists and Maybe:
GHCi> :set -XTypeApplications
GHCi> :t traverse #[] #Maybe
traverse #[] #Maybe :: (a -> Maybe b) -> [a] -> Maybe [b]
It works like this: you give it an a -> Maybe b function, which is applied to all elements of the list, just like fmap does. The twist is that the Maybe b values are then combined in a way that only gives you a modified list if there aren't any Nothings; otherwise, the overall result is Nothing. That fits your requirements like a glove:
noneOrNothing :: (a -> Bool) -> [a] -> Maybe [a]
noneOrNothing p = traverse (\x -> if p x then Nothing else Just x)
(allOrNothing would have been a more euphonic name, but then I'd have to flip the test with respect to your description.)
There are a lot of things we might discuss about the Traversable and Applicative classes. For now, I will talk a bit more about Applicative, in case you haven't met it yet. Applicative is a superclass of Monad with two essential methods: pure, which is the same thing as return, and (<*>), which is not entirely unlike (>>=) but crucially different from it. For the Maybe example...
GHCi> :t (>>=) #Maybe
(>>=) #Maybe :: Maybe a -> (a -> Maybe b) -> Maybe b
GHCi> :t (<*>) #Maybe
(<*>) #Maybe :: Maybe (a -> b) -> Maybe a -> Maybe b
... we can describe the difference like this: in mx >>= f, if mx is a Just-value, (>>=) reaches inside of it to apply f and produce a result, which, depending on what was inside mx, will turn out to be a Just-value or a Nothing. In mf <*> mx, though, if mf and mx are Just-values you are guaranteed to get a Just value, which will hold the result of applying the function from mf to the value from mx. (By the way: what will happen if mf or mx are Nothing?)
traverse involves Applicative because the combining of values I mentioned at the beginning (which, in your example, turns a number of Maybe a values into a Maybe [a]) is done using (<*>). As your question was originally about monads, it is worth noting that it is possible to define traverse using Monad rather than Applicative. This variation goes by the name mapM:
mapM :: (Traversable t, Monad m) => (a -> m b) -> t a -> m (t b)
We prefer traverse to mapM because it is more general -- as mentioned above, Applicative is a superclass of Monad.
On a closing note, your intuition about this being "a sort of filter" makes a lot of sense. In particular, one way to think about Maybe a is that it is what you get when you pick booleans and attach values of type a to True. From that vantage point, (<*>) works as an && for these weird booleans, which combines the attached values if you happen to supply two of them (cf. DarthFennec's suggestion of an implementation using any). Once you get used to Traversable, you might enjoy having a look at the Filterable and Witherable classes, which play with this relationship between Maybe and Bool.
duplode's answer is a good one, but I think it is also helpful to learn to operate within a monad in a more basic way. It can be a challenge to learn every little monad-general function, and see how they could fit together to solve a specific problem. So, here's a DIY solution that shows how to use do notation and recursion, tools which can help you with any monadic question.
forbid :: (a -> Bool) -> [a] -> Maybe [a]
forbid _ [] = Just []
forbid p (x:xs) = if p x
then Nothing
else do
remainder <- forbid p xs
Just (x : remainder)
Compare this to an implementation of remove, the opposite of filter:
remove :: (a -> Bool) -> [a] -> [a]
remove _ [] = []
remove p (x:xs) = if p x
then remove p xs
else
let remainder = remove p xs
in x : remainder
The structure is the same, with just a couple differences: what you want to do when the predicate returns true, and how you get access to the value returned by the recursive call. For remove, the returned value is a list, and so you can just let-bind it and cons to it. With forbid, the returned value is only maybe a list, and so you need to use <- to bind to that monadic value. If the return value was Nothing, bind will short-circuit the computation and return Nothing; if it was Just a list, the do block will continue, and cons a value to the front of that list. Then you wrap it back up in a Just.

When to use foldr with a continuation as an accumulation function?

There is a technique I've seen a few times with foldr. It involves using a function in place of the accumulator in a foldr. I'm wondering when it is necessary to do this, as opposed to using an accumulator that is just a regular value.
Most people have seen this technique before when using foldr to define foldl:
myFoldl :: forall a b. (b -> a -> b) -> b -> [a] -> b
myFoldl accum nil as = foldr f id as nil
where
f :: a -> (b -> b) -> b -> b
f a continuation b = continuation $ accum b a
Here, the type of the combining function f is not just a -> b -> b like normal, but a -> (b -> b) -> b -> b. It takes not only an a and b, but a continuation (b -> b) that we need to pass the b to in order to get the final b.
I most recently saw an example of using this trick in the book Parallel and Concurrent Programming in Haskell. Here is a link to the source code of the example using this trick. Here is a link to the chapter of the book explaining this example.
I've taken the liberty of simplifying the source code into a similar (but shorter) example. Below is a function that takes a list of Strings, prints out whether each string's length is greater than five, then prints the full list of only the Strings that have a length greater than five:
import Text.Printf
stringsOver5 :: [String] -> IO ()
stringsOver5 strings = foldr f (print . reverse) strings []
where
f :: String -> ([String] -> IO ()) -> [String] -> IO ()
f str continuation strs = do
let isGreaterThan5 = length str > 5
printf "Working on \"%s\", greater than 5? %s\n" str (show isGreaterThan5)
if isGreaterThan5
then continuation $ str : strs
else continuation strs
Here's an example of using it from GHCi:
> stringsOver5 ["subdirectory", "bye", "cat", "function"]
Working on "subdirectory", greater than 5? True
Working on "bye", greater than 5? False
Working on "cat", greater than 5? False
Working on "function", greater than 5? True
["subdirectory","function"]
Just like in the myFoldl example, you can see that the combining function f is using the same trick.
However, it occurred to me that this stringsOver5 function could probably be written without this trick:
stringsOver5PlainFoldr :: [String] -> IO ()
stringsOver5PlainFoldr strings = foldr f (pure []) strings >>= print
where
f :: String -> IO [String] -> IO [String]
f str ioStrs = do
let isGreaterThan5 = length str > 5
printf "Working on \"%s\", greater than 5? %s\n" str (show isGreaterThan5)
if isGreaterThan5
then fmap (str :) ioStrs
else ioStrs
(Although maybe you could make the argument that IO [String] is a continuation?)
I have two questions regarding this:
Is it every absolutely necessary to use this trick of passing a continuation to foldr, instead of using foldr with a normal value as an accumulator? Is there an example of a function that absolutely can't be written using foldr with a normal value? (Aside from foldl and functions like that, of course.)
When would I want to use this trick in my own code? Is there any example of a function that can be significantly simplified by using this trick?
Is there any sort of performance considerations to take into account when using this trick? (Or, well, when not using this trick?)
I have two questions regarding this:
For some large value of "two" :-P
Is it every absolutely necessary to use this trick of passing a continuation to foldr? Is there an example of a function that
absolutely can't be written without this trick? (Aside from foldl and
functions like that, of course.)
No, never. Each foldr invocation can always be replaced by explicit recursion.
One should use foldr and other well-known library functions when they make the code simpler. When they do not, one should not shoehorn the code so that it fits the foldr pattern.
There is no shame in using plain recursion, when there is no obvious replacement.
Compare your code with this, for instance:
stringsOver5 :: [String] -> IO ()
stringsOver5 strings = go strings []
where
go :: [String] -> [String] -> IO ()
go [] acc = print (reverse acc)
go (s:ss) acc = do
let isGreaterThan5 = length str > 5
printf "Working on \"%s\", greater than 5? %s\n" str (show isGreaterThan5)
if isGreaterThan5
then go ss (s:acc)
else go ss acc
When would I want to use this trick in my own code? Is there any example of a function that can be significantly simplified by using
this trick?
In my humble opinion, almost never.
Personally, I find "calling foldr with four (or more) arguments" to be an anti-pattern in most cases. This is because it is not that shorter than using explicit recursion, and has the potential to be much less readable.
I would argue that this "idiom" is quite puzzling to any Haskeller who has not seen it before. It is a sort-of an acquired taste, so to speak.
Perhaps, it could be a good idea to use this style when the continuation functions are meaningful on their own. E.g., when representing lists as difference lists, the concatenation of a regular-list of difference-lists can be quite elegant
foldr (.) id listOfDLists []
is beautiful, even if the last [] might be puzzling at first.
Is there any sort of performance considerations to take into account when using this trick? (Or, well, when not using this trick?)
Performance should be essentially the same as using explicit recursion. GHC could even generate the exact same code.
Perhaps using foldr could help GHC fire some fold/build optimization rules, but I'm unsure about the need to do that when using continuations.

Most efficient way of building a list in a left fold?

When building lists, I usually use a right fold, as that lets me use the right-associative : operator without affecting the order of the resulting list. In a left fold, I could use ++, but I understand that this will entail repeatedly copying the list while it is being produced, giving O(N^2) operations for an N-element list, which is generally unacceptable.
So, when I have to use a left fold (in my specific case this is because I'm using foldlM and the monadic actions produced must be performed in left-to-right order), is there any better way of reconciling this other than building the list in the fold using : and reversing the result?
when I have to use a left fold (... because ... the monadic actions produced must be performed in left-to-right order)
Right fold can lean so far right that it comes back left again. For example, you can print (i.e. monadic action) each number and calculate partial sums of a list from left to right using a right fold:
fun :: [Int] -> IO [Int]
fun xs = foldr go (const $ return []) xs 0
where go x f a = let a' = a + x in print x >> (a' :) <$> f a'
then:
\> fun [1..5]
1
2
3
4
5
[1,3,6,10,15]
note that the output list is built using (a' :) and the monadic action is performed left to right, even though it is a right fold.
Since you mention foldlM, likely this blog post of mine answers your question in depth:
Constructing a list in a Monad
The bottom line is: Use difference lists; i.e. in your left-fold, you accumulate a value of type [a] -> [a], where you can append a value using . (x:) efficiently, and at the end you apply this function to [] to obtain your list.

Functional Programming-Style Map Function that adds elements?

I know and love my filter, map and reduce, which happen to be part of more and more languages that are not really purely functional.
I found myself needing a similar function though: something like map, but instead of one to one it would be one to many.
I.e. one element of the original list might be mapped to multiple elements in the target list.
Is there already something like this out there or do I have to roll my own?
This is exactly what >>= specialized to lists does.
> [1..6] >>= \x -> take (x `mod` 3) [1..]
[1,1,2,1,1,2]
It's concatenating together the results of
> map (\x -> take (x `mod` 3) [1..]) [1..6]
[[1],[1,2],[],[1],[1,2],[]]
You do not have to roll your own. There are many relevant functions here, but I'll highlight three.
First of all, there is the concat function, which already comes in the Prelude (the standard library that's loaded by default). What this function does, when applied to a list of lists, is return the list that contains concatenated contents of the sublists.
EXERCISE: Write your own version of concat :: [[a]] -> [a].
So using concat together with map, you could write this function:
concatMap :: (a -> [b]) -> [a] -> [b]
concatMap f = concat . map f
...except that you don't actually need to write it, because it's such a common pattern that the Prelude already has it (at a more general type than what I show hereā€”the library version takes any Foldable, not just lists).
Finally, there is also the Monad instance for list, which can be defined this way:
instance Monad [] where
return a = [a]
as >>= f = concatMap f as
So the >>= operator (the centerpiece of the Monad class), when working with lists, is exactly the same thing as concatMap.
EXERCISE: Skim through the documentation of the Data.List module. Figure out how to import the module into your code and play around with some of the functions.

Define a haskell function [IO a] -> IO[a]

I am doing a haskell exercise, regarding define a function accumulate :: [IO a] -> IO [a]
which performs a sequence of interactions and accumulates their result in a list.
What makes me confused is how to express a list of IO a ? (action:actions)??
how to write recursive codes using IO??
This is my code, but these exists some problem...
accumulate :: [IO a] -> IO [a]
accumulate (action:actions) = do
value <- action
list <- accumulate (action:actions)
return (convert_to_list value list)
convert_to_list:: Num a =>a -> [a]-> [a]
convert_to_list a [] = a:[]
convert_to_list x xs = x:xs
What you are trying to implement is sequence from Control.Monad.
Just to let you find the answer instead of giving it, try searching for [IO a] -> IO [a] on hoogle (there's a Source link on the right hand side of the page when you've chosen a function).
Try to see in your code what happens when list of actions is empty list and see what does sequence do to take care of that.
There is already such function in Control.Monad and it called sequence (no you shouldn't look at it). You should denote the important decision taken during naming of it. Technically [IO a] says nothing about in which order those Monads should be attached to each other, but name sequence puts a meaning of sequential attaching.
As for the solving you problem. I'd suggest to look more at types and took advice of #sacundim. In GHCi (interpreter from Glasgow Haskell Compiler) there is pretty nice way to check type and thus understand expression (:t (:) will return (:) :: a -> [a] -> [a] which should remind you one of you own function but with less restrictive types).
First of all I'd try to see at what you have showed with more simple example.
data MyWrap a = MyWrap a
accumulate :: [MyWrap a] -> MyWrap [a]
accumulate (action:actions) = MyWrap (convert_to_list value values) where
MyWrap value = action -- use the pattern matching to unwrap value from action
-- other variant is:
-- value = case action of
-- MyWrap x -> x
MyWrap values = accumulate (action:actions)
I've made the same mistake that you did on purpose but with small difference (values is a hint). As you probably already have been told you could try to interpret any of you program by trying to inline appropriate functions definitions. I.e. match definitions on the left side of equality sign (=) and replace it with its right side. In your case you have infinite cycle. Try to solve it on this sample or your and I think you'll understand (btw your problem might be just a typo).
Update: Don't be scary when your program will fall in runtime with message about pattern match. Just think of case when you call your function as accumulate []
Possibly you looking for sequence function that maps [m a] -> m [a]?
So the short version of the answer to your question is, there's (almost) nothing wrong with your code.
First of all, it typechecks:
Prelude> let accumulate (action:actions) = do { value <- action ;
list <- accumulate (action:actions) ; return (value:list) }
Prelude> :t accumulate
accumulate :: (Monad m) => [m t] -> m [t]
Why did I use return (value:list) there? Look at your second function, it's just (:). Calling g
g a [] = a:[]
g a xs = a:xs
is the same as calling (:) with the same arguments. This is what's known as "eta reduction": (\x-> g x) === g (read === as "is equivalent").
So now just one problem remains with your code. You've already taken a value value <- action out of the action, so why do you reuse that action in list <- accumulate (action:actions)? Do you really have to? Right now you have, e.g.,
accumulate [a,b,c] ===
do { v1<-a; ls<-accumulate [a,b,c]; return (v1:ls) } ===
do { v1<-a; v2<-a; ls<-accumulate [a,b,c]; return (v1:v2:ls) } ===
do { v1<-a; v2<-a; v3<-a; ls<-accumulate [a,b,c]; return (v1:v2:v3:ls) } ===
.....
One simple fix and you're there.

Resources