1-- |
2-- Module      : Foundation.Collection.List
3-- License     : BSD-style
4-- Maintainer  : Vincent Hanquez <vincent@snarc.org>
5-- Stability   : experimental
6-- Portability : portable
7--
8module Foundation.Collection.List
9    ( wordsWhen
10    , revTake
11    , revDrop
12    , revSplitAt
13    , breakEnd
14    , uncons
15    , unsnoc
16    ) where
17
18import qualified Data.List
19import           Data.Tuple (swap)
20import           Basement.Compat.Base
21import           Foundation.Numerical
22
23-- | Simple helper to split a list repeatly when the predicate match
24wordsWhen     :: (x -> Bool) -> [x] -> [[x]]
25wordsWhen _ [] = [[]]
26wordsWhen p is = loop is
27  where
28    loop s =
29        let (w, s') = Data.List.break p s
30         in case s' of
31                []   -> [w]
32                _:xs -> w : loop xs
33
34revTake :: Int -> [a] -> [a]
35revTake n l = Data.List.drop (len - n) l
36  where
37    len = Data.List.length l
38
39revDrop :: Int -> [a] -> [a]
40revDrop n l = Data.List.take (len - n) l
41  where
42    len = Data.List.length l
43
44revSplitAt :: Int -> [a] -> ([a],[a])
45revSplitAt n l = swap $ Data.List.splitAt (len - n) l
46  where
47    len = Data.List.length l
48
49breakEnd :: (a -> Bool) -> [a] -> ([a], [a])
50breakEnd predicate l =
51    let (l1,l2) = Data.List.break predicate (Data.List.reverse l)
52     in if Data.List.null l2 then (l, []) else (Data.List.reverse l2, Data.List.reverse l1)
53
54uncons :: [a] -> Maybe (a, [a])
55uncons []     = Nothing
56uncons (x:xs) = Just (x,xs)
57
58unsnoc :: [a] -> Maybe ([a], a)
59unsnoc []       = Nothing
60unsnoc [x]      = Just ([], x)
61unsnoc [x,y]    = Just ([x], y)
62unsnoc (x:xs@(_:_)) = Just $ loop [x] xs
63  where
64    loop acc [y]    = (Data.List.reverse acc, y)
65    loop acc (y:ys) = loop (y:acc) ys
66    loop _   _      = error "impossible"
67