Skip to content

Commit 6846b6c

Browse files
safarelipaf31
authored andcommitted
add stripPrefix for List.Lazy (#126)
1 parent 25a25b0 commit 6846b6c

File tree

2 files changed

+39
-6
lines changed

2 files changed

+39
-6
lines changed

src/Data/List/Lazy.purs

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@ module Data.List.Lazy
5757
-- , sort
5858
-- , sortBy
5959

60+
, Pattern(..)
61+
, stripPrefix
6062
, slice
6163
, take
6264
, takeWhile
@@ -96,21 +98,20 @@ import Prelude
9698
import Control.Alt ((<|>))
9799
import Control.Alternative (class Alternative)
98100
import Control.Lazy as Z
99-
101+
import Control.Monad.Rec.Class as Rec
100102
import Data.Foldable (class Foldable, foldr, any, foldl)
103+
import Data.Foldable (foldl, foldr, foldMap, fold, intercalate, elem, notElem, find, findMap, any, all) as Exports
101104
import Data.Lazy (defer)
102105
import Data.List.Lazy.Types (List(..), Step(..), step, nil, cons, (:))
103106
import Data.List.Lazy.Types (NonEmptyList(..)) as NEL
104107
import Data.Maybe (Maybe(..), isNothing)
105-
import Data.Newtype (unwrap)
108+
import Data.Newtype (class Newtype, unwrap)
106109
import Data.NonEmpty ((:|))
110+
import Data.Traversable (scanl, scanr) as Exports
107111
import Data.Traversable (sequence)
108112
import Data.Tuple (Tuple(..))
109113
import Data.Unfoldable (class Unfoldable, unfoldr)
110114

111-
import Data.Foldable (foldl, foldr, foldMap, fold, intercalate, elem, notElem, find, findMap, any, all) as Exports
112-
import Data.Traversable (scanl, scanr) as Exports
113-
114115
-- | Convert a list into any unfoldable structure.
115116
-- |
116117
-- | Running time: `O(n)`
@@ -472,6 +473,34 @@ catMaybes = mapMaybe id
472473
-- Sublists --------------------------------------------------------------------
473474
--------------------------------------------------------------------------------
474475

476+
477+
-- | A newtype used in cases where there is a list to be matched.
478+
newtype Pattern a = Pattern (List a)
479+
480+
derive instance eqPattern :: Eq a => Eq (Pattern a)
481+
derive instance ordPattern :: Ord a => Ord (Pattern a)
482+
derive instance newtypePattern :: Newtype (Pattern a) _
483+
484+
instance showPattern :: Show a => Show (Pattern a) where
485+
show (Pattern s) = "(Pattern " <> show s <> ")"
486+
487+
488+
-- | If the list starts with the given prefix, return the portion of the
489+
-- | list left after removing it, as a Just value. Otherwise, return Nothing.
490+
-- | * `stripPrefix (Pattern (fromFoldable [1])) (fromFoldable [1,2]) == Just (fromFoldable [2])`
491+
-- | * `stripPrefix (Pattern (fromFoldable [])) (fromFoldable [1]) == Just (fromFoldable [1])`
492+
-- | * `stripPrefix (Pattern (fromFoldable [2])) (fromFoldable [1]) == Nothing`
493+
-- |
494+
-- | Running time: `O(n)` where `n` is the number of elements to strip.
495+
stripPrefix :: forall a. Eq a => Pattern a -> List a -> Maybe (List a)
496+
stripPrefix (Pattern p') s = Rec.tailRecM2 go p' s
497+
where
498+
go prefix input = case step prefix of
499+
Nil -> Just $ Rec.Done input
500+
Cons p ps -> case step input of
501+
Cons i is | p == i -> Just $ Rec.Loop { a: ps, b: is }
502+
_ -> Nothing
503+
475504
-- | Extract a sublist by a start and end index.
476505
slice :: Int -> Int -> List ~> List
477506
slice start end xs = take (end - start) (drop start xs)

test/Test/Data/List/Lazy.purs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import Control.Monad.Eff (Eff)
77
import Control.Monad.Eff.Console (CONSOLE, log)
88

99
import Data.Lazy as Z
10-
import Data.List.Lazy (List, nil, cons, foldl, foldr, foldMap, singleton, transpose, take, iterate, filter, uncons, foldM, foldrLazy, range, unzip, zip, length, zipWithA, replicate, repeat, zipWith, intersectBy, intersect, deleteBy, delete, unionBy, union, nubBy, nub, groupBy, group, partition, span, dropWhile, drop, takeWhile, slice, catMaybes, mapMaybe, filterM, concat, concatMap, reverse, alterAt, modifyAt, updateAt, deleteAt, insertAt, findLastIndex, findIndex, elemLastIndex, elemIndex, init, tail, last, head, insertBy, insert, snoc, null, replicateM, fromFoldable, (:), (\\), (!!))
10+
import Data.List.Lazy (List, nil, stripPrefix, Pattern(..), cons, foldl, foldr, foldMap, singleton, transpose, take, iterate, filter, uncons, foldM, foldrLazy, range, unzip, zip, length, zipWithA, replicate, repeat, zipWith, intersectBy, intersect, deleteBy, delete, unionBy, union, nubBy, nub, groupBy, group, partition, span, dropWhile, drop, takeWhile, slice, catMaybes, mapMaybe, filterM, concat, concatMap, reverse, alterAt, modifyAt, updateAt, deleteAt, insertAt, findLastIndex, findIndex, elemLastIndex, elemIndex, init, tail, last, head, insertBy, insert, snoc, null, replicateM, fromFoldable, (:), (\\), (!!))
1111
import Data.List.Lazy.NonEmpty as NEL
1212
import Data.Maybe (Maybe(..), isNothing, fromJust)
1313
import Data.Monoid.Additive (Additive(..))
@@ -25,6 +25,10 @@ testListLazy = do
2525
l = fromFoldable
2626
nel xxs = NEL.NonEmptyList (Z.defer \_ -> xxs)
2727
longList = range 1 100000
28+
log "strip prefix"
29+
assert $ stripPrefix (Pattern (l [1])) (l [1,2]) == Just (l [2])
30+
assert $ stripPrefix (Pattern (l [])) (l [1]) == Just (l [1])
31+
assert $ stripPrefix (Pattern (l [2])) (l [1]) == Nothing
2832

2933
log "append should be stack-safe"
3034
assert $ length (longList <> longList) == (2 * length longList)

0 commit comments

Comments
 (0)