简体   繁体   中英

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM