Haskell - How to traverse through a list and reverse elements - haskell

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.

Related

Haskell function that goes through each pair in list and returns a list with size smaller than original by 1

Suppose we have list [1,2,3,4].
I want to take every pair of consecutive elements (i.e. (1,2),(2,3),(3,4)), apply them to some function, and return list which consist of results of this function.
I don't quite understand, how to do this on haskell, since we don't actually have loops and arrays here.
Here are some ways you could try to solve this. The first step will be to get the pairs and the second will be applying the function to the pairs. One way to do the first step is with a recursive function. Now in Haskell lists are made using [] and :, with [1,2,3] being syntactic sugar for 1:(2:(3:[])). So let us write our function:
window [] = []
window [a] = []
window [a,b] = [(a,b)]
window (a:b:r) = (a,b):window (b:r)
Another way we could do this is with the function zip. Recall that this takes two lists, pairs up their elements, and ends the list when either input ends.
window [] = []
window xs = zip xs (tail xs)
The second step is to apply our function to the pairs. We can do this with map (uncurry f). All together:
onWindow f = map (uncurry f) . window
There's several approaches that could work here.
You could use recursion:
mapCons :: (a -> a -> b) -> [a] -> [b]
-- input has at least two elements
mapCons f (a0:a1:as) =
-- use them to compute the head of the output
f a0 a1 :
-- reuse the second element to compute the tail of the output
mapCons f (a1:as)
-- input has less than two elements, so output is the empty list
mapCons _ _ = []
Alternately, zip converts a pair of lists into a list of pairs:
λ zip [1..10] ['a'..'z']
[(1,'a'),(2,'b'),(3,'c'),(4,'d'),(5,'e'),(6,'f'),(7,'g'),(8,'h'),(9,'i'),(10,'j')]
This gives a way to generate all the consecutive pairs in a list by zipping a list with its own tail:
λ zip [1..10] ['a'..'z']
[(1,'a'),(2,'b'),(3,'c'),(4,'d'),(5,'e'),(6,'f'),(7,'g'),(8,'h'),(9,'i'),(10,'j')]
You could then use map to run your function on each pair in the list
λ map (\(a,b) -> 10*a + b) $ zip [0..9] (tail [0..9])
[1,12,23,34,45,56,67,78,89]
This is a common enough pattern that there's a function that combines map and zip: zipWith:
λ :t zipWith
zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]
λ zipWith (\a b -> 10*a + b) [0..9] (tail [0..9])
[1,12,23,34,45,56,67,78,89]

How to filter a list by another list in Haskell?

Suppose I have two lists A and B of the same length. I want to keep elements in A which are greater than corresponding elements in B. Let A=[1,5,8], B=[2,4,9], the result should be [5] because 1<2, 5>4, 8<9.
I come up with a solution. Let C=zip A B, then filter C, finally get result by taking fst of each element in C. It's not so elegant. Is there a simpler way?
Code:
map fst (filter (\ x-> (fst x) > (snd x)) (zip a b))
Your described solution looks fine to me.
An alternative which is not necessarily better:
import Data.Maybe
import Control.Monad
catMaybes $ zipWith (\a b -> guard (a>b) >> return a) list1 list2
According to the desugaring of monad comprehensions this should also work
{-# LANGUAGE MonadComprehensions #-}
[ a | ( a <- list1 | b <- list2 ), a > b ]
... but in practice it does not. It is a pity because I find it quite elegant.
I wonder whether I got it wrong or it is a GHC bug.
I was working on something similar and as a newbie this is the best I came up with:
filterGreaterThan xs ys = do (x,y) <- zip xs ys
guard (x > y)
return x
This solution is easier to reason about than the others. The do notation really shines here.
I'm not sure how your code looks but the following function look quite elegant to me:
greater :: Ord a => [a] -> [a] -> [a]
greater xs = map fst . filter ((>) <$> fst <*> snd) . zip xs
example :: [Int]
example = greater [1,5,8] [2,4,9] -- result is [5]
This pattern is well known in the Lisp community as the decorate-process-undecorate pattern.
A recursive approach, not so elegant as (any) of the other approaches, this relies on no explicit zipping and we get the result in one pass,
greater :: Ord a => [a] -> [a] -> [a]
greater [] [] = []
greater (x:xs) (y:ys)
| x > y = x : greater xs ys
| otherwise = greater xs ys
If you want to generalize this idea nicely, I would recommend looking to mapMaybe:
mapMaybe
:: (a -> Maybe b)
-> [a] -> [b]
Applying that idea to zipWith yields
zipWithMaybe
:: (a -> b -> Maybe c)
-> [a] -> [b] -> [c]
zipWithMaybe f xs ys =
[c | Just c <- zipWith f xs ys]
Now you can write your function
keepGreater :: Ord a => [a] -> [a] -> [a]
keepGreater = zipWithMaybe $
\x y -> x <$ guard (x > y)
Is it really worth the trouble? For lists, probably not. But something like this turns out to be useful in the context of merges for Data.Map.
Pretty similar to #chi's solution with Lists concant:
concat $ zipWith (\a b -> last $ []:[[a] | a > b]) as bs

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

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])

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.)

Lack of understanding infinite lists and seq operator

The code below retains, for a given integer n, the first n items from a list, drops the following n items, keeps the following n and so on. It works correctly for any finite list.
In order to make it usable with infinite lists, I used the 'seq' operator to force the accumulator evaluation before the recursive step as in foldl' as example.
I tested by tracing the accumulator's value and it seems that it is effectively computed as desired with finite lists.
Nevertheless, it doesn't work when applied to an infinite list. The "take" in the main function is only executed once the inner calculation is terminated, what, of course, never happens with an infinite list.
Please, can someone tell me where is my mistake?
main :: IO ()
main = print (take 2 (foo 2 [1..100]))
foo :: Show a => Int -> [a] -> [a]
foo l lst = inFoo keepOrNot 1 l lst []
inFoo :: Show a => (Bool -> Int -> [a] -> [a] -> [a]) -> Int -> Int -> [a] -> [a] -> [a]
inFoo keepOrNot i l [] lstOut = lstOut
inFoo keepOrNot i l lstIn lstOut = let lstOut2 = (keepOrNot (odd i) l lstIn lstOut) in
stOut2 `seq` (inFoo keepOrNot (i+1) l (drop l lstIn) lstOut2)
keepOrNot :: Bool -> Int -> [a] -> [a] -> [a]
keepOrNot b n lst1 lst2 = case b of
True -> lst2 ++ (take n lst1)
False -> lst2
Here's how list concatenation is implemented:
(++) :: [a] -> [a] -> [a]
(++) [] ys = ys
(++) (x:xs) ys = x : xs ++ ys
Note that
the right hand list structure is reused as is (even if it's not been evaluated yet, so lazily)
the left hand list structure is rewritten (copied)
This means that if you're using ++ to build up a list, you want the accumulator to be on the right hand side. (For finite lists, merely for efficiency reasons --- if the accumulator is on the left hand side, it will be repeatedly copied and this is inefficient. For infinite lists, the caller can't look at the first element of the result until it's been copied for the last time, and there won't be a last time because there's always something else to concatenate onto the right of the accumulator.)
The True case of keepOrNot has the accumulator on the left of the ++. You need to use a different data structure.
The usual idiom in this case is to use difference lists. Instead of using type [a] for your accumulator, use [a] -> [a]. Your accumulator is now a function that prepends a list to the list it's given as input. This avoids repeated copying, and the list can be built lazily.
keepOrNot :: Bool -> Int -> [a] -> ([a] -> [a]) -> ([a] -> [a])
keepOrNot b n lst1 acc = case b of
True -> acc . (take n lst1 ++)
False -> acc
The initial value of the accumulator should be id. When you want to convert it to a conventional list, call it with [] (i.e., acc []).
seq is a red herring here. seq does not force the entire list. seq only determines whether it is of the form [] or x : xs.
You're learning Haskell, yes? So it would be a good idea as an exercise to modify your code to use a difference list accumulator. Possibly the use of infinite lists will burn you in a different part of your code; I don't know.
But there is a better approach to writing foo.
foo c xs = map snd . filter fst . zipWith f [0..] $ xs
where f i x = (even (i `div` c), x)
So you want to group a list into groups of n elements, and drop every other group. We can write this down directly:
import Data.List (unfoldr)
groups n xs = takeWhile (not.null) $ unfoldr (Just . splitAt n) xs
foo c xs = concatMap head . groups 2 . groups c $ xs
dave4420 already explained what is wrong with your code, but I'd like to comment on how you got there, IMO. Your keepOrNot :: Bool -> Int -> [a] -> [a] -> [a] function is too general. It works according to the received Bool, any Bool; but you know that you will feed it a succession of alternating True and False values. Programming with functions is like plugging a pipe into a funnel - output of one function serves as input to the next - and the funnel is too wide here, so the contact is loose.
A minimal re-write of your code along these lines could be
foo n lst = go lst
where
go lst = let (a,b) = splitAt n lst
(c,d) = splitAt n b
in
a ++ go d
The contact is "tight", there's no "information leakage" here. We just do the work twice (*) ourselves, and "connect the pipes" explicitly, in this code, grabbing one result (a) and dropping the other (c).
--
(*) twice, reflecting the two Boolean values, True and False, alternating in a simple fashion one after another. Thus this is captured frozen in the code's structure, not hanging loose as a parameter able to accommodate an arbitrary Boolean value.
Like dava4420 said, you shouldn't be using (++) to accumulate from the left. But perhaps you shouldn't be accumulating at all! In Haskell, lazyness makes straighforward "head-construction" often more efficient than the tail recursions you'd need to use in e.g. Lisp. For example:
foo :: Int -> [a] -> [a] -- why would you give this a Show constraint?
foo ℓ = foo' True
where foo' _ [] = []
foo' keep lst
| keep = firstℓ ++ foo' False other
| otherwise = foo' True other
where (firstℓ, other) = splitAt ℓ lst

Resources