How to get rid of boxing and unboxing in functional programing? - haskell

says that we want to filter out all the odd one in a list.
odd' (i,n) = odd i
unbox (i,n) = n
f :: [Int] -> [Int]
f lst = map unbox $ filter odd' $ zip [1..] lst
*Main> f [1,2,3,4]
[1,3]
it has the unpleasant boxing and unboxing.
can we change the way we think this problem and eliminate boxing and unboxing?
#user3237465 list comprehension is indeed a good way of thinking this sort of problem.
as well as function composition. well, I think we won't get rid of "wrapping the original list to [(index,value)] form and then unwrap it" without writing a special form like #Carsten König provided.
Or have a function that give out one value's index given the list and the value. like filter (odd . getindex) xs
and maybe that's why clojure made it's pattern matching strong enough to get value in complex structure.

you can always rewrite the function if you want - this comes to mind:
odds :: [a] -> [a]
odds (x:_:xs) = x : odds xs
odds [x] = [x]
odds _ = []
aside from this both you don't need odd' and unbox:
odd' is just odd . fst
unbox is just snd

You can write this as
f xs = [x | (i, x) <- zip [0..] xs, even i]
or
f = snd . foldr (\x ~(o, e) -> (e, x : o)) ([], [])
or
import Data.Either
f = lefts . zipWith ($) (cycle [Left, Right])

Related

Haskell - How to traverse through a list and reverse elements

I am having trouble locating documentation on simple operations in Haskell.
I have a list of lists (:: [[a]]) and I need to reverse all of the element lists x where length x >= 2.
So far I haven't found anything on:
How to traverse the lists
How would I find the length of the element. There is the length function I can use, but I haven't got an idea how to use it.
I did find the reverse function for lists, though I had trouble finding it.
If any help on those individual implementation, it would be greatly appreciated. I can piece them together.
I need to reverse all of the element lists x where length x >= 2
You can totally ignore the length x >= 2 part, since if the length of a list is 0 or 1, reversing it has no effect: there's no way to tell whether you reversed it or not, so you might as well just reverse all lists, for uniformity.
Given that, this is super simple: you just need to map reverse over the list of lists, reversing each one in turn:
reverseEach :: [[a]] -> [[a]]
reverseEach = map reverse
> reverseEach [[1,2,3],[4],[5,6,7,8]]
[[3,2,1],[4],[8,7,6,5]]
And as other answers suggest, you can afford to generalize a little bit:
reverseEach :: Functor f => f [a] -> f [a]
reverseEach = fmap reverse
> reverseEach [[1,2,3],[4],[5,6,7,8]]
[[3,2,1],[4],[8,7,6,5]]
how to traverse the lists.
There are several sequence functions, from the more basic fmap, which maps a single function over a list, to foldr, which folds a list structure around a binary operation (for summing a list or similar operations) to the sequence/traverse operations, which carry monadic or applicative effects.
How would I find the length of the element. There is the length function I can use, but I haven't got an idea how to use it.
There is a length function; you use it like any other function. length xs, where xs is a list. If you still aren't certain how to do that, I would suggest starting slower with a Haskell tutorial.
And I have this to reverse the list, But i think i have that now.
There is a reverse function. If you don't want to use the built-in one (or if you want to do it yourself for educational purposes), you could build an efficient reverse function with an accumulator.
reverse' :: [a] -> [a]
reverse' xs = doReverse xs []
where doReverse [] ys = ys
doReverse (x:xs) ys = doReverse xs (x:ys)
Solution:
conditionallyReverse :: [[a]] -> [[a]]
ConditionallyReverse listOfLists= fmap f listOfLists
where
f list
| length list >= 2 = reverse x
| otherwise = x
We apply the function f to each element of the listOfLists by supplying f as the first argument to fmap and the listOfLists as the second argument. The function f transforms a list based on the condition length list >= 2. If the condition holds, the list is reversed, otherwise the original list is returned.
Absurd over-generalization:
Every Traversable instance supports a horrible hack implementing reverse. There may be a cleaner or more efficient way to do this; I'm not sure.
module Rev where
import Data.Traversable
import Data.Foldable
import Control.Monad.Trans.State.Strict
import Prelude hiding (foldl)
fill :: Traversable t => t b -> [a] -> t a
fill = evalState . traverse go
where
go _ = do
xs <- get
put (drop 1 xs)
return (head xs)
reverseT :: Traversable t => t a -> t a
reverseT xs = fill xs $ foldl (flip (:)) [] xs
reverseAll :: (Functor f, Traversable t) => f (t a) -> f (t a)
reverseAll = fmap reverseT
In terms of folds:
reverse = foldl (\ acc x -> x : acc) []
length = foldl' (\ n _ -> n + 1) 0
map f = foldr (\ x xs -> f x : xs)
letting
mapReverse = map (\ xs -> if length xs >= 2 then reverse xs else xs)
But length is a costly O(n), and reverse [x] = [x]. I would use
map reverse [[1,2,3],[4],[]] == [[3,2,1],[4],[]]
where (map reverse) :: [[a]] -> [[a]]. map reverse isn't basic enough to justify an own name binding.

Haskell - format issue

i am a beginner in haskell programming and very often i get the error
xxx.hs:30:1: parse error on input `xxx'
And often there is a little bit playing with the format the solution. Its the same code and it looks the same, but after playing around, the error is gone.
At the moment I've got the error
LookupAll.hs:30:1: parse error on input `lookupAll'
After that code:
lookupOne :: Int -> [(Int,a)] -> [a]
lookupOne _ [] = []
lookupOne x list =
if fst(head list) == x then snd(head list) : []
lookupOne x (tail list)
-- | Given a list of keys and a list of pairs of key and value
-- 'lookupAll' looks up the list of associated values for each key
-- and concatenates the results.
lookupAll :: [Int] -> [(Int,a)] -> [a]
lookupAll [] _ = []
lookupAll _ [] = []
lookupAll xs list = lookupOne h list ++ lookupAll t list
where
h = head xs
t = tail xs
But I have done everything right in my opinion. There are no tabs or something like that. Always 4 spaces. Is there a general solutoin for this problems? I am using notepad++ at the moment.
Thanks!
The problem is not with lookupAll, it's actually with the previous two lines of code
if fst (head list) == x then snd (head list) : []
lookupOne x (tail list)
You haven't included an else on this if statement. My guess is that you meant
if fst (head list) == x then snd (head list) : []
else lookupOne x (tail list)
Which I personally would prefer to format as
if fst (head list) == x
then snd (head list) : []
else lookupOne x (tail list)
but that's a matter of taste.
If you are wanting to accumulate a list of values that match a condition, there are a few ways. By far the easiest is to use filter, but you can also use explicit recursion. To use filter, you could write your function as
lookupOne x list
= map snd -- Return only the values from the assoc list
$ filter (\y -> fst y == x) list -- Find each pair whose first element equals x
If you wanted to use recursion, you could instead write it as
lookupOne _ [] = [] -- The base case pattern
lookupOne x (y:ys) = -- Pattern match with (:), don't have to use head and tail
if fst y == x -- Check if the key and lookup value match
then snd y : lookupOne x ys -- If so, prepend it onto the result of looking up the rest of the list
else lookupOne x ys -- Otherwise, just return the result of looking up the rest of the list
Both of these are equivalent. In fact, you can implement filter as
filter cond [] = []
filter cond (x:xs) =
if cond x
then x : filter cond xs
else filter cond xs
And map as
map f [] = []
map f (x:xs) = f x : map f xs
Hopefully you can spot the similarities between filter and lookupOne, and with map consider f == snd, so you have a merger of the two patterns of map and filter in the explicit recursive version of lookupOne. You could generalize this combined pattern into a higher order function
mapFilter :: (a -> b) -> (a -> Bool) -> [a] -> [b]
mapFilter f cond [] = []
mapFilter f cond (x:xs) =
if cond x
then f x : mapFilter f cond xs
else : mapFilter f cond xs
Which you can use to implement lookupOne as
lookupOne x list = mapFilter snd (\y -> fst y == x) list
Or more simply
lookupOne x = mapFilter snd ((== x) . fst)
I think #bheklilr is right - you're missing an else.
You could fix this particular formatting problem, however, by forming lookupOne as a function composition, rather than writing your own new recursive function.
For example, you can get the right kind of behaviour by defining lookupOne like this:
lookupOne a = map snd . filter ((==) a . fst)
This way it's clearer that you're first filtering out the elements of the input list for which the first element of the tuple matches the key, and then extracting just the second element of each tuple.

Haskell from List of Pairs to Pair of Lists

I want to create a simple (involving sets and lists) function that can do the following, and i'm not sure where to start.
split:: [(a,b)] -> ([a],[b])
Let's take it step by step. The two cases for the function are:
split [] = ???
split ((a,b):ps) = ???
One case is easy enough.
split [] = ([], [])
For the other one, we have to use the function recursively, someway
split ((a,b):ps) = ???? where
(as, bs) = split ps
I think it's easy to see that the solution is
split ((a,b):ps) = (a:as, b:bs) where
(as, bs) = split ps
In addition to Guido's solution, there is more than one way to do it in haskell.
Please take a look at fst and snd, which takes the first / second element out of a pair, respectively.
GHCi> :t fst
fst :: (a, b) -> a
GHCi> :t snd
snd :: (a, b) -> b
You should be familiar with map if you are playing with functional programming languages, which takes a function and a list, applies the function on every element of that list, and gives you all the results in another list:
GHCi> :t map
map :: (a -> b) -> [a] -> [b]
Given a list of pairs, you want two lists, one contains all first elements in order, and the other contains all second elements:
GHCi> let split xs = (map fst xs, map snd xs)
GHCi> split [(1,2),(3,4),(5,6)]
([1,3,5],[2,4,6])
GHCi>
One step further, as #jozefg has pointed out in the comment, that this method is not efficient as #Guido 's one, but we can make some changes to improve it (which is exactly what #Guido 's solution):
Now it's time to take a look at how map is implemented here
map :: (a -> b) -> [a] -> [b]
map _ [] = []
map f (x:xs) = f x : map f xs
so we can try to change our split a little:
we still need the base case, (i.e. what if xs is empty):
split [] = ([], [])
split ls = (map fst ls, map snd ls) -- attention!
and we break the list into head and tail, just like map:
split (x:xs) = (fst x: map fst xs, snd x: map snd xs)
Now we can do a pattern matching, (a,b) = x, so we don't have to call two individual functions to break a pair into two:
split (x:xs) = (a: map fst xs, b: map snd xs)
where (a,b) = x
Compare the code here with the line I commented "attention!", have you realized that if we know the result of (map fst xs, map snd xs), we can simply reuse that result to speed up. Luckily, we already have split ls = (map fst ls, map snd ls)!
Using this fact, we finally come up with this version:
split [] = ([], [])
split (x:xs) = (a:as , b:bs)
where (a,b) = x
(as,bs) = split xs
So there are essentially the same! (but as you can see, the last version we have is more efficient.)

implementation of unzip function in haskell

I am trying to implement the unzip function, I did the following code but I get error.
myUnzip [] =()
myUnzip ((a,b):xs) = a:fst (myUnzip xs) b:snd (myUnzip xs)
I know that problem is in the right side of the second line but I do know how to improve it .
any hint please .
the error that I am getting is
ex1.hs:190:22:
Couldn't match expected type `()' with actual type `[a0]'
In the expression: a : fst (myUnzip xs) b : snd (myUnzip xs)
In an equation for `myUnzip':
myUnzip ((a, b) : xs) = a : fst (myUnzip xs) b : snd (myUnzip xs)
ex1.hs:190:29:
Couldn't match expected type `(t0 -> a0, b0)' with actual type `()'
In the return type of a call of `myUnzip'
In the first argument of `fst', namely `(myUnzip xs)'
In the first argument of `(:)', namely `fst (myUnzip xs) b'
ex1.hs:190:49:
Couldn't match expected type `(a1, [a0])' with actual type `()'
In the return type of a call of `myUnzip'
In the first argument of `snd', namely `(myUnzip xs)'
In the second argument of `(:)', namely `snd (myUnzip xs)'
You could do it inefficiently by traversing the list twice
myUnzip [] = ([], []) -- Defaults to a pair of empty lists, not null
myUnzip xs = (map fst xs, map snd xs)
But this isn't very ideal, since it's bound to be quite slow compared to only looping once. To get around this, we have to do it recursively
myUnzip [] = ([], [])
myUnzip ((a, b):xs) = (a : ???, b : ???)
where ??? = myUnzip xs
I'll let you fill in the blanks, but it should be straightforward from here, just look at the type signature of myUnzip and figure out what you can possible put in place of the question marks at where ??? = myUnzip xs
I thought it might be interesting to display two alternative solutions. In practice you wouldn't use these, but they might open your mind to some of the possibilities of Haskell.
First, there's the direct solution using a fold -
unzip' xs = foldr f x xs
where
f (a,b) (as,bs) = (a:as, b:bs)
x = ([], [])
This uses a combinator called foldr to iterate through the list. Instead, you just define the combining function f which tells you how to combine a single pair (a,b) with a pair of lists (as, bs), and you define the initial value x.
Secondly, remember that there is the nice-looking solution
unzip'' xs = (map fst xs, map snd xs)
which looks neat, but performs two iterations of the input list. It would be nice to be able to write something as straightforward as this, but which only iterates through the input list once.
We can nearly achieve this using the Foldl library. For an explanation of why it doesn't quite work, see the note at the end - perhaps someone with more knowledge/time can explain a fix.
First, import the library and define the identity fold. You may have to run cabal install foldl first in order to install the library.
import Control.Applicative
import Control.Foldl
ident = Fold (\as a -> a:as) [] reverse
You can then define folds that extract the first and second components of a list of pairs,
fsts = map fst <$> ident
snds = map snd <$> ident
And finally you can combine these two folds into a single fold that unzips the list
unzip' = (,) <$> fsts <*> snds
The reason that this doesn't quite work is that although you only traverse the list once to extract the pairs, they will be extracted in reverse order. This is what necessitates the additional call to reverse in the definition of ident, which results in an extra traversal of the list, to put it in the right order. I'd be interested to learn of a way to fix that up (I expect it's not possible with the current Foldl library, but might be possible with an analogous Foldr library that gives up streaming in order to preserve the order of inputs).
Note that neither of these work with infinite lists. The solution using Foldl will never be able to handle infinite lists, because you can't observe the value of a left fold until the list has terminated.
However, the version using a right fold should work - but at the moment it isn't lazy enough. In the definition
unzip' xs = foldr f x xs
where
f (a,b) (as,bs) = (a:as, b:bs) -- problem is in this line!
x = ([], [])
the pattern match requires that we open up the tuple in the second argument, which requires evaluating one more step of the fold, which requires opening up another tuple, which requires evaluating one more step of the fold, etc. However, if we use an irrefutable pattern match (which always succeeds, without having to examine the pattern) we get just the right amount of laziness -
unzip'' xs = foldr f x xs
where
f (a,b) ~(as,bs) = (a:as, b:bs)
x = ([], [])
so we can now do
>> let xs = repeat (1,2)
>> take 10 . fst . unzip' $ xs
^CInterrupted
<< take 10 . fst . unzip'' $ xs
[1,1,1,1,1,1,1,1,1,1]
Here's Chris Taylor's answer written using the (somewhat new) "folds" package:
import Data.Fold (R(R), run)
import Control.Applicative ((<$>), (<*>))
ident :: R a [a]
ident = R id (:) []
fsts :: R (a, b) [a]
fsts = map fst <$> ident
snds :: R (a, b) [b]
snds = map snd <$> ident
unzip' :: R (a, b) ([a], [b])
unzip' = (,) <$> fsts <*> snds
test :: ([Int], [Int])
test = run [(1,2), (3,4), (5,6)] unzip'
*Main> test
([1,3,5],[2,4,6])
Here is what I got working after above guidances
myUnzip' [] = ([],[])
myUnzip' ((a,b):xs) = (a:(fst rest), b:(snd rest))
where rest = myUnzip' xs
myunzip :: [(a,b)] -> ([a],[b])
myunzip xs = (firstValues xs , secondValues xs)
where
firstValues :: [(a,b)] -> [a]
firstValues [] = []
firstValues (x : xs) = fst x : firstValues xs
secondValues :: [(a,b)] -> [b]
secondValues [] = []
secondValues (x : xs) = snd x : secondValues xs

Haskell program to replicate elements in List

I am new to Haskell.
I am trying to write a program which given a list as an input replicates each element of list k times, where k = position of element in list.
e.g. replic[5,6,7] gives [[5],[6,6],[7,7,7]].
Another condition is solution has to use map function.
Till now code I have written is :
replic [] = []
replic (x:xs) = map (replicate 2 ) [x] ++ replic xs
This replicates every element twice as replicate has input parameter 2.
What I need is replicate function should be given input as 1 ,2 ,3 in consecutive calls. So I need a counter. How can I use the counter there or do anything else that will give me position of element?
Expanding on Satvik, the notation
[1..]
gives you an infinite list of numbers counting up.
The function zip associates allows you to merge two lists into a list of tuples
zip :: [a] -> [b] -> [(a,b)]
for example
> zip [1..] [5,6,7]
[(1,5),(2,6),(3,7)]
this code associates each value in the list with its position in the list
now
replicate :: Int -> a -> [a]
repeats a value an arbitrary number of times. Given these two components, we can design a simple function
replic xs = map (\(a,b) -> replicate a b) (zip [1..] xs)
which I would write pointfree as
replic :: [a] -> [[a]]
replic = map (uncurry replicate) . zip [1..]
this does exactly what you want
> replic [5,6,7]
[[5],[6,6],[7,7,7]]
There are many ways of doing this
Here is a solution similar to what you tried to do. zipping the list with list [1..] gives you the counter you wanted.
replic = repl . zip [1..]
repl [] = []
repl ((x,y):xs) = (replicate x y) : (repl xs)
Another solution using just map
replic = map f . zip [1..]
where
f (c,l) = replicate c l
If you don't like idea of using zip you can also use mapAccumL
import Data.List
replic = snd . mapAccumL f 1
where
f a v = (a+1,replicate a v)
Usually you would write:
replic = zipWith replicate [1..]
Now you can write your own zipWith yourself using map:
zipWith' f xs ys = map (uncurry f) $ zip xs ys
Note that you don't necessarily need an index, e.g.
import Data.List
replic xs = reverse $ transpose (tail $ inits $ reverse xs)
You can do something like this with map when using explicit recursion:
replic = f . map return where
f [] = []
f (x:xs) = x : f (map (\(x:xs) -> x:x:xs) xs)

Resources