Skip to content

Commit 3e746ab

Browse files
joshuahhhpaf31
authored andcommitted
Add unsnoc (#94)
* Add unsnoc * Implement unsnoc in a single pass * unsnocHelper => go * More consistent style
1 parent ec4b522 commit 3e746ab

File tree

2 files changed

+25
-7
lines changed

2 files changed

+25
-7
lines changed

src/Data/List.purs

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ module Data.List
3131
, tail
3232
, init
3333
, uncons
34+
, unsnoc
3435

3536
, (!!), index
3637
, elemIndex
@@ -242,12 +243,7 @@ tail (_ : xs) = Just xs
242243
-- |
243244
-- | Running time: `O(n)`
244245
init :: forall a. List a -> Maybe (List a)
245-
init Nil = Nothing
246-
init lst = Just $ reverse $ go lst Nil
247-
where
248-
go (x : Nil) acc = acc
249-
go (x : xs) acc = go xs (x : acc)
250-
go _ acc = acc
246+
init lst = _.init <$> unsnoc lst
251247

252248
-- | Break a list into its first element, and the remaining elements,
253249
-- | or `Nothing` if the list is empty.
@@ -257,6 +253,17 @@ uncons :: forall a. List a -> Maybe { head :: a, tail :: List a }
257253
uncons Nil = Nothing
258254
uncons (x : xs) = Just { head: x, tail: xs }
259255

256+
-- | Break a list into its last element, and the preceding elements,
257+
-- | or `Nothing` if the list is empty.
258+
-- |
259+
-- | Running time: `O(n)`
260+
unsnoc :: forall a. List a -> Maybe { init :: List a, last :: a }
261+
unsnoc lst = (\h -> { init: reverse h.revInit, last: h.last }) <$> go lst Nil
262+
where
263+
go Nil acc = Nothing
264+
go (x : Nil) acc = Just { revInit: acc, last: x }
265+
go (x : xs) acc = go xs (x : acc)
266+
260267
--------------------------------------------------------------------------------
261268
-- Indexed operations ----------------------------------------------------------
262269
--------------------------------------------------------------------------------

test/Test/Data/List.purs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import Data.List.NonEmpty as NEL
55
import Control.Monad.Eff (Eff)
66
import Control.Monad.Eff.Console (CONSOLE, log)
77
import Data.Foldable (foldMap, foldl)
8-
import Data.List (List(..), (..), length, range, foldM, unzip, zip, zipWithA, zipWith, intersectBy, intersect, (\\), deleteBy, delete, unionBy, union, nubBy, nub, groupBy, group', group, span, dropWhile, drop, takeWhile, take, sortBy, sort, catMaybes, mapMaybe, filterM, filter, concat, concatMap, reverse, alterAt, modifyAt, updateAt, deleteAt, insertAt, findLastIndex, findIndex, elemLastIndex, elemIndex, (!!), uncons, init, tail, last, head, insertBy, insert, snoc, null, singleton, fromFoldable, transpose, mapWithIndex, (:))
8+
import Data.List (List(..), (..), length, range, foldM, unzip, zip, zipWithA, zipWith, intersectBy, intersect, (\\), deleteBy, delete, unionBy, union, nubBy, nub, groupBy, group', group, span, dropWhile, drop, takeWhile, take, sortBy, sort, catMaybes, mapMaybe, filterM, filter, concat, concatMap, reverse, alterAt, modifyAt, updateAt, deleteAt, insertAt, findLastIndex, findIndex, elemLastIndex, elemIndex, (!!), uncons, unsnoc, init, tail, last, head, insertBy, insert, snoc, null, singleton, fromFoldable, transpose, mapWithIndex, (:))
99
import Data.Maybe (Maybe(..), isNothing, fromJust)
1010
import Data.Monoid.Additive (Additive(..))
1111
import Data.NonEmpty ((:|))
@@ -106,6 +106,17 @@ testList = do
106106
assert $ unsafePartial (fromJust u2).head == 1
107107
assert $ unsafePartial (fromJust u2).tail == l [2, 3]
108108

109+
log "unsnoc should return nothing when used on an empty list"
110+
assert $ isNothing (unsnoc nil)
111+
112+
log "unsnoc should split an list into an init and last record when there is at least one item"
113+
let v1 = unsnoc (l [1])
114+
assert $ unsafePartial (fromJust v1).init == l []
115+
assert $ unsafePartial (fromJust v1).last == 1
116+
let v2 = unsnoc (l [1, 2, 3])
117+
assert $ unsafePartial (fromJust v2).init == l [1, 2]
118+
assert $ unsafePartial (fromJust v2).last == 3
119+
109120
log "(!!) should return Just x when the index is within the bounds of the list"
110121
assert $ l [1, 2, 3] !! 0 == (Just 1)
111122
assert $ l [1, 2, 3] !! 1 == (Just 2)

0 commit comments

Comments
 (0)