HORIZON HASKELLDocslts/ghc-10.0.x8174fa42026-10-11Search names, modules, packages, or :: a typeCtrl K

GHC 10.0.0.20260917 · lts/ghc-10.0.x · 8174fa4 · 2026-10-11

Modulenonempty-containers-0.3.6.0Haskell2010

Data.Sequence.NonEmpty

Non-Empty Finite Sequences

| An NESeq a is a non-empty (but finite) sequence of values of type a. Generally has the same interface as NonEmpty. This is a non-empty version of Seq from Data.Sequence.

The main differences between this type and NonEmpty are:

  • You cannot have infinite NESeqs

  • You have constant-time consing from either end, and constant-time unconsing as well (through <|, |>, :<||, and :||>)

  • Concatenation (><, |><, ><|) is logarithmic-time.

  • You have logarithmic-time indexing and updating at a given index.

While asymptotics are often better than for NonEmpty, there is a decent constant factor involved in most operations.

See documentation for NESeq for information on how to convert and manipulate such non-empty sequences

This module essentially re-imports the API of Data.Sequence.Lazy and its Seq type, along with semantics and asymptotics.

Because NESeq is implemented using Seq, all of the caveats of using Seq apply.

All functions take non-empty sequences as inputs. In situations where their results can be guarunteed to also be non-empty, they also return non-empty maps. In situations where their results could potentially be empty, Seq is returned instead.

Some functions (like spanl, spanr, breakl, breakr, partition, splitAt) have modified return types to account for possible configurations of non-emptiness.

Some functions (head, last, tail, init) are provided because they are total for non-empty sequences.

This module is intended to be imported qualified, to avoid name clashes with Prelude and Data.Sequence functions:

import qualified Data.Sequence.NonEmpty as NESeq
  • 1 type
  • 84 values

Finite sequences

3 declarations
datadata NESeq a
#

A general-purpose non-empty (by construction) finite sequence type.

Non-emptiness means that:

  • Functions that take an NESeq can safely operate on it with the assumption that it has at least value.

  • Functions that return an NESeq provide an assurance that the result has at least one value.

Data.Sequence.NonEmpty re-exports the API of Data.Sequence, faithfully reproducing asymptotics, typeclass constraints, and semantics. Functions that ensure that input and output maps are both non-empty (like <|) return NESeq, but functions that might potentially return an empty map (like tail) return a Seq instead.

You can directly construct an NESeq with the API from Data.Sequence.NonEmpty; it's more or less the same as constructing a normal Seq, except you don't have access to Data.Seq.empty. There are also a few ways to construct an NESeq from a Seq:

  1. The nonEmptySeq smart constructor will convert a Seq a into a Maybe (NESeq a), returning Nothing if the original Seq was empty.

  2. You can use :<||, :||>, and insertSeqAt to insert a value into a Seq to create a guaranteed NESeq.

  3. You can use the IsNonEmpty and IsEmpty patterns to "pattern match" on a Seq to reveal it as either containing a NESeq or an empty sequence.

  4. withNonEmpty offers a continuation-based interface for deconstructing a Seq and treating it as if it were an NESeq.

You can convert an NESeq into a Seq with toSeq or IsNonEmpty, essentially "obscuring" the non-empty property from the type.

Instances34Monad, Functor, MonadFix, Applicative, Foldable, Traversable, …
  • Monad NESeqDefined in nonempty-containers-0.3.6.0 · Data.Sequence.NonEmpty.Internal
  • Functor NESeqDefined in nonempty-containers-0.3.6.0 · Data.Sequence.NonEmpty.Internal
  • MonadFix NESeqDefined in nonempty-containers-0.3.6.0 · Data.Sequence.NonEmpty.Internal
  • Applicative NESeqDefined in nonempty-containers-0.3.6.0 · Data.Sequence.NonEmpty.Internal
  • Foldable NESeqDefined in nonempty-containers-0.3.6.0 · Data.Sequence.NonEmpty.Internal

    foldr1, foldl1, maximum, and minimum are all total, unlike for Seq.

  • Traversable NESeqDefined in nonempty-containers-0.3.6.0 · Data.Sequence.NonEmpty.Internal
  • MonadZip NESeqDefined in nonempty-containers-0.3.6.0 · Data.Sequence.NonEmpty.Internal
    mzipWith = zipWith
    munzip = unzip
  • Foldable1 NESeqDefined in nonempty-containers-0.3.6.0 · Data.Sequence.NonEmpty.Internal
  • Eq1 NESeqDefined in nonempty-containers-0.3.6.0 · Data.Sequence.NonEmpty.Internal
  • Ord1 NESeqDefined in nonempty-containers-0.3.6.0 · Data.Sequence.NonEmpty.Internal
  • Read1 NESeqDefined in nonempty-containers-0.3.6.0 · Data.Sequence.NonEmpty.Internal
  • Show1 NESeqDefined in nonempty-containers-0.3.6.0 · Data.Sequence.NonEmpty.Internal
  • Comonad NESeqDefined in nonempty-containers-0.3.6.0 · Data.Sequence.NonEmpty.Internal
  • Alt NESeqDefined in nonempty-containers-0.3.6.0 · Data.Sequence.NonEmpty.Internal
  • Apply NESeqDefined in nonempty-containers-0.3.6.0 · Data.Sequence.NonEmpty.Internal
  • Bind NESeqDefined in nonempty-containers-0.3.6.0 · Data.Sequence.NonEmpty.Internal
  • Extend NESeqDefined in nonempty-containers-0.3.6.0 · Data.Sequence.NonEmpty.Internal
  • Traversable1 NESeqDefined in nonempty-containers-0.3.6.0 · Data.Sequence.NonEmpty.Internal
  • Invariant NESeqDefined in nonempty-containers-0.3.6.0 · Data.Sequence.NonEmpty.Internal
  • FoldableWithIndex Int NESeqDefined in nonempty-containers-0.3.6.0 · Data.Sequence.NonEmpty.Internal
  • FunctorWithIndex Int NESeqDefined in nonempty-containers-0.3.6.0 · Data.Sequence.NonEmpty.Internal
  • TraversableWithIndex Int NESeqDefined in nonempty-containers-0.3.6.0 · Data.Sequence.NonEmpty.Internal
  • IsList (NESeq a)Defined in nonempty-containers-0.3.6.0 · Data.Sequence.NonEmpty.Internal
  • Eq a => Eq (NESeq a)Defined in nonempty-containers-0.3.6.0 · Data.Sequence.NonEmpty.Internal
  • Data a => Data (NESeq a)Defined in nonempty-containers-0.3.6.0 · Data.Sequence.NonEmpty.Internal
  • Ord a => Ord (NESeq a)Defined in nonempty-containers-0.3.6.0 · Data.Sequence.NonEmpty.Internal
  • Read a => Read (NESeq a)Defined in nonempty-containers-0.3.6.0 · Data.Sequence.NonEmpty.Internal
  • Show a => Show (NESeq a)Defined in nonempty-containers-0.3.6.0 · Data.Sequence.NonEmpty.Internal
  • Semigroup (NESeq a)Defined in nonempty-containers-0.3.6.0 · Data.Sequence.NonEmpty.Internal
  • NFData a => NFData (NESeq a)Defined in nonempty-containers-0.3.6.0 · Data.Sequence.NonEmpty.Internal
  • FromJSON a => FromJSON (NESeq a)Defined in nonempty-containers-0.3.6.0 · Data.Sequence.NonEmpty.Internal
  • ToJSON a => ToJSON (NESeq a)Defined in nonempty-containers-0.3.6.0 · Data.Sequence.NonEmpty.Internal
  • IsNonEmptyList (NESeq a)Defined in nonempty-containers-0.3.6.0 · Data.Containers.NonEmpty.List
  • type Item (NESeq a) = aDefined in nonempty-containers-0.3.6.0 · Data.Sequence.NonEmpty.Internal
patternpattern (:<||) :: a -> Seq a -> NESeq a
#

O(1). An abstract constructor for an NESeq that consists of a "head" a and a "tail" Seq a. Similar to :| for NonEmpty.

Can be used to match on the head and tail of an NESeq, and also used to construct an NESeq by consing an item to the beginnong of a Seq, ensuring that the result is non-empty.

patternpattern (:||>) :: Seq a -> a -> NESeq a
#

O(1). An abstract constructor for an NESeq that consists of a "init" Seq a and a "last" a. Similar to :| for NonEmpty, but at the end of the list instead of at the beginning.

Can be used to match on the init and last of an NESeq, and also used to construct an NESeq by snocing an item to the end of a Seq, ensuring that the result is non-empty.

Conversions between empty and non-empty sequences

patternpattern IsNonEmpty :: NESeq a -> Seq a
#

O(1). The IsNonEmpty and IsEmpty patterns allow you to treat a Seq as if it were either a IsNonEmpty n (where n is a NESeq) or an IsEmpty.

For example, you can pattern match on a Seq:

safeHead :: Seq Int -> Int
safeHead (IsNonEmpty (x :<|| _))  = x  -- here, user provided a non-empty sequence, and n is the NESeq
safeHead IsEmpty                  = 0  -- here the user provided an empty sequence

Matching on IsNonEmpty n means that the original Seq was not empty, and you have a verified-non-empty NESeq n to use.

A case statement handling both IsNonEmpty and IsEmpty provides complete coverage.

This is a bidirectional pattern, so you can use IsNonEmpty to convert a NESeq back into a Seq, obscuring its non-emptiness (see toSeq).

valuenonEmptySeq :: Seq a -> Maybe (NESeq a)
#

O(1). Smart constructor for an NESeq from a Seq. Returns Nothing if the Seq was originally actually empty, and Just n with an NESeq, if the Seq was not empty.

nonEmptySeq and maybe empty toSeq form an isomorphism: they are perfect structure-preserving inverses of eachother.

See IsNonEmpty for a pattern synonym that lets you "match on" the possiblity of a Seq being an NESeq.

nonEmptySeq (Data.Sequence.fromList [1,2,3]) == Just (fromList (1) :| [2,3])
valuetoSeq :: NESeq a -> Seq a
#

O(1). Convert a non-empty sequence back into a normal possibly-empty sequence, for usage with functions that expect Seq.

Can be thought of as "obscuring" the non-emptiness of the map in its type. See the Data.Sequence.NonEmpty.IsNotEmpty pattern.

nonEmptySeq and maybe Data.Seq.empty toSeq form an isomorphism: they are perfect structure-preserving inverses of eachother.

valueinsertSeqAt :: Int -> a -> Seq a -> NESeq a
#

Turn a Seq into a guarantted non-empty NESeq by adding an element at a given index.

insertSeqAt 1 0 (Data.Sequence.fromList [1,2,3]) == fromList (1 :| [0,2,3])

Construction

8 declarations
value(<|) :: a -> NESeq a -> NESeq a
#

O(1) . Add an element to the left end of a non-empty sequence. Mnemonic: a triangle with the single element at the pointy end.

value(|>) :: NESeq a -> a -> NESeq a
#

O(1) . Add an element to the right end of a non-empty sequence. Mnemonic: a triangle with the single element at the pointy end.

value(><) :: NESeq a -> NESeq a -> NESeq a
#

O(\log(\min(n_1,n_2))) . Concatenate two non-empty sequences.

value(|><) :: NESeq a -> Seq a -> NESeq a
#

O(\log(\min(n_1,n_2))) . Concatenate a non-empty sequence with a potentially empty sequence (Seq), to produce a guaranteed non-empty sequence. Mnemonic: like ><, but a pipe for the guarunteed non-empty side.

value(><|) :: Seq a -> NESeq a -> NESeq a
#

O(\log(\min(n_1,n_2))) . Concatenate a non-empty sequence with a potentially empty sequence (Seq), to produce a guaranteed non-empty sequence. Mnemonic: like ><, but a pipe for the guarunteed non-empty side.

valuefromFunction :: Int -> (Int -> a) -> NESeq a
#

O(n) . Convert a given sequence length and a function representing that sequence into a sequence.

Repetition

valuereplicate :: Int -> a -> NESeq a
#

O(\log n) . replicate n x is a sequence consisting of n copies of x. Is only defined when n is positive.

valuecycleTaking :: Int -> NESeq a -> NESeq a
#

O(log k). cycleTaking k xs forms a sequence of length k by repeatedly concatenating xs with itself. Is only defined when k is positive.

Property
cycleTaking k = fromList . fromJust . nonEmpty . take k . cycle . toList

Iterative construction

valueiterateN :: Int -> (a -> a) -> a -> NESeq a
#

O(n) . Constructs a sequence by repeated application of a function to a seed value. Is only defined if given a positive value.

iterateN n f x = fromList (fromJust (nonEmpty ((Prelude.take n (Prelude.iterate f x)))))
valueunfoldr :: (b -> (a, Maybe b)) -> b -> NESeq a
#

Builds a sequence from a seed value. Takes time linear in the number of generated elements. WARNING: If the number of generated elements is infinite, this method will not terminate.

Deconstruction

4 declarations

Additional functions for deconstructing sequences are available via the Foldable instance of NESeq.

valuehead :: NESeq a -> a
#

O(1). Retrieve the left-most item in a non-empty sequence. Note that this function is total.

valuetail :: NESeq a -> Seq a
#

O(1). Delete the left-most item in a non-empty sequence. Returns a potentially empty sequence (Seq) in the case that the original NESeq contained only a single element. Note that this function is total.

valuelast :: NESeq a -> a
#

O(1). Retrieve the right-most item in a non-empty sequence. Note that this function is total.

valueinit :: NESeq a -> Seq a
#

O(1). Delete the right-most item in a non-empty sequence. Returns a potentially empty sequence (Seq) in the case that the original NESeq contained only a single element. Note that this function is total.

Queries

valuelength :: NESeq a -> Int
#

O(1) . The number of elements in the sequence.

Scans

4 declarations
valuescanl :: (a -> b -> a) -> a -> NESeq b -> NESeq a
#

scanl is similar to foldl, but returns a sequence of reduced values from the left:

scanl f z (fromList [x1, x2, ...]) = fromList [z, z `f` x1, (z `f` x1) `f` x2, ...]
valuescanl1 :: (a -> a -> a) -> NESeq a -> NESeq a
#

scanl1 is a variant of scanl that has no starting value argument:

scanl1 f (fromList [x1, x2, ...]) = fromList [x1, x1 `f` x2, ...]

Sublists

3 declarations
valuetails :: NESeq a -> NESeq (NESeq a)
#

O(n) . Returns a sequence of all non-empty suffixes of this sequence, longest first. For example,

tails (fromList (1:|[2,3])) = fromList (fromList (1:|[2,3]) :| [fromList (2:|[3]), fromList (3:|[])])

Evaluating the i th suffix takes O(\log(\min(i, n-i))) , but evaluating every suffix in the sequence takes O(n) due to sharing.

valueinits :: NESeq a -> NESeq (NESeq a)
#

O(n) . Returns a sequence of all non-empty prefixes of this sequence, shortest first. For example,

tails (fromList (1:|[2,3])) = fromList (fromList (1:|[]) :| [fromList (1:|[2]), fromList (1:|[2,3]))

Evaluating the i th prefix takes O(\log(\min(i, n-i))) , but evaluating every prefix in the sequence takes O(n) due to sharing.

valuechunksOf :: Int -> NESeq a -> NESeq (NESeq a)
#

O \Bigl(\bigl(\frac{n}{c}\bigr) \log c\Bigr). chunksOf c xs splits xs into chunks of size c>0. If c does not divide the length of xs evenly, then the last element of the result will be short. Is only defined if c is a positive number.

Side note: the given performance bound is missing some messy terms that only really affect edge cases. Performance degrades smoothly from O(1) (for c = n ) to O(n) (for c = 1 ). The true bound is more like O \Bigl( \bigl(\frac{n}{c} - 1\bigr) (\log (c + 1)) + 1 \Bigr)

Sequential searches

valuetakeWhileL :: (a -> Bool) -> NESeq a -> Seq a
#

O(i) where i is the prefix length. takeWhileL, applied to a predicate p and a sequence xs, returns the longest prefix (possibly empty) of xs of elements that satisfy p.

Returns a possibly empty sequence (Seq) in the case that the predicate fails on the first item.

valuetakeWhileR :: (a -> Bool) -> NESeq a -> Seq a
#

O(i) where i is the suffix length. takeWhileR, applied to a predicate p and a sequence xs, returns the longest suffix (possibly empty) of xs of elements that satisfy p.

Returns a possibly empty sequence (Seq) in the case that the predicate fails on the first item.

takeWhileR p xs is equivalent to reverse (takeWhileL p (reverse xs)).

valuedropWhileL :: (a -> Bool) -> NESeq a -> Seq a
#

O(i) where i is the prefix length. dropWhileL p xs returns the suffix remaining after takeWhileL p xs.

Returns a possibly empty sequence (Seq) in the case that the predicate passes for all items.

valuespanl :: (a -> Bool) -> NESeq a -> These (NESeq a) (NESeq a)
#

O(i) where i is the prefix length. spanl, applied to a predicate p and a sequence xs, returns a These based on the point where the predicate fails:

  • This ys means that the predicate was true for all items, and ys is the entire original sequence.

  • That zs means that the predicate failed on the first item, and zs is the entire original sequence.

  • These ys zs gives ys (the prefix of elements that satisfy the predicae) and zs (the remainder of the sequence)

valuespanr :: (a -> Bool) -> NESeq a -> These (NESeq a) (NESeq a)
#

O(i) where i is the suffix length. spanr, applied to a predicate p and a sequence xs, returns a These based on the point where the predicate fails:

  • This ys means that the predicate was true for all items, and ys is the entire original sequence.

  • That zs means that the predicate failed on the first item, and zs is the entire original sequence.

  • These ys zs gives ys (the suffix of elements that satisfy the predicae) and zs (the remainder of the sequence, before the suffix)

valuepartition :: (a -> Bool) -> NESeq a -> These (NESeq a) (NESeq a)
#

O(n) . The partition function takes a predicate p and a sequence xs and returns sequences of those elements which do and do not satisfy the predicate, as a These:

  • This ys means that the predicate was true for all items, and ys is the entire original sequence.

  • That zs means that the predicate failed on the first item, and zs is the entire original sequence.

  • These ys zs gives ys (the sequence of elements for which the predicate was true) and zs (the sequence of elements for which the predicate was false).

valuefilter :: (a -> Bool) -> NESeq a -> Seq a
#

O(n) . The filter function takes a predicate p and a sequence xs and returns a sequence of those elements which satisfy the predicate.

Returns a potentially empty sequence (Seq) in the case that the predicate fails for all items in the sequence.

Sorting

6 declarations
valuesort :: Ord a => NESeq a -> NESeq a
#

O(n \log n) . sort sorts the specified NESeq by the natural ordering of its elements. The sort is stable. If stability is not required, unstableSort can be slightly faster.

valuesortOn :: Ord b => (a -> b) -> NESeq a -> NESeq a
#

O(n \log n) . sortOn sorts the specified NESeq by comparing the results of a key function applied to each element. sortOn f is equivalent to sortBy (compare `Data.Function.on` f), but has the performance advantage of only evaluating f once for each element in the input list. This is called the decorate-sort-undecorate paradigm, or Schwartzian transform.

An example of using sortOn might be to sort a NESeq of strings according to their length:

sortOn length (fromList ("alligator" :| ["monkey", "zebra"])) == fromList ("zebra" :| ["monkey", "alligator"])

If, instead, sortBy had been used, length would be evaluated on every comparison, giving O(n \log n) evaluations, rather than O(n) .

If f is very cheap (for example a record selector, or fst), sortBy (compare `Data.Function.on` f) will be faster than sortOn f.

valueunstableSort :: Ord a => NESeq a -> NESeq a
#

O(n \log n) . unstableSort sorts the specified NESeq by the natural ordering of its elements, but the sort is not stable. This algorithm is frequently faster and uses less memory than sort.

valueunstableSortOn :: Ord b => (a -> b) -> NESeq a -> NESeq a
#

O(n \log n) . unstableSortOn sorts the specified NESeq by comparing the results of a key function applied to each element. unstableSortOn f is equivalent to unstableSortBy (compare `Data.Function.on` f), but has the performance advantage of only evaluating f once for each element in the input list. This is called the decorate-sort-undecorate paradigm, or Schwartzian transform.

An example of using unstableSortOn might be to sort a NESeq of strings according to their length.

unstableSortOn length (fromList ("alligator" :| ["monkey", "zebra"])) == fromList ("zebra" :| ["monkey", "alligator]")

If, instead, unstableSortBy had been used, length would be evaluated on every comparison, giving O(n \log n) evaluations, rather than O(n) .

If f is very cheap (for example a record selector, or fst), unstableSortBy (compare `Data.Function.on` f) will be faster than unstableSortOn f.

Indexing

11 declarations
valuelookup :: Int -> NESeq a -> Maybe a
#

O(\log(\min(i,n-i))) . The element at the specified position, counting from 0. If the specified position is negative or at least the length of the sequence, lookup returns Nothing.

Unlike index, this can be used to retrieve an element without forcing it.

valueindex :: NESeq a -> Int -> a
#

O(\log(\min(i,n-i))) . The element at the specified position, counting from 0. The argument should thus be a non-negative integer less than the size of the sequence. If the position is out of range, index fails with an error.

Property
xs `index` i = toList xs !! i

Caution: index necessarily delays retrieving the requested element until the result is forced. It can therefore lead to a space leak if the result is stored, unforced, in another structure. To retrieve an element immediately without forcing it, use lookup or (!?).

valueadjust :: (a -> a) -> Int -> NESeq a -> NESeq a
#

O(\log(\min(i,n-i))) . Update the element at the specified position. If the position is out of range, the original sequence is returned. adjust can lead to poor performance and even memory leaks, because it does not force the new value before installing it in the sequence. adjust' should usually be preferred.

valueadjust' :: (a -> a) -> Int -> NESeq a -> NESeq a
#

O(\log(\min(i,n-i))) . Update the element at the specified position. If the position is out of range, the original sequence is returned. The new value is forced before it is installed in the sequence.

adjust' f i xs =
 case xs !? i of
   Nothing -> xs
   Just x -> let !x' = f x
             in update i x' xs
valueupdate :: Int -> a -> NESeq a -> NESeq a
#

O(\log(\min(i,n-i))) . Replace the element at the specified position. If the position is out of range, the original sequence is returned.

valuetake :: Int -> NESeq a -> Seq a
#

O(\log(\min(i,n-i))) . The first i elements of a sequence. If i is negative, take i s yields the empty sequence. If the sequence contains fewer than i elements, the whole sequence is returned.

valuedrop :: Int -> NESeq a -> Seq a
#

O(\log(\min(i,n-i))) . Elements of a sequence after the first i. If i is negative, drop i s yields the whole sequence. If the sequence contains fewer than i elements, the empty sequence is returned.

valueinsertAt :: Int -> a -> NESeq a -> NESeq a
#

O(\log(\min(i,n-i))) . insertAt i x xs inserts x into xs at the index i, shifting the rest of the sequence over.

insertAt 2 x (fromList (a:|[b,c,d])) = fromList (a:|[b,x,c,d])
insertAt 4 x (fromList (a:|[b,c,d])) = insertAt 10 x (fromList (a:|[b,c,d]))
                                     = fromList (a:|[b,c,d,x])
Property
insertAt i x xs = take i xs >< singleton x >< drop i xs
valuedeleteAt :: Int -> NESeq a -> Seq a
#

O(\log(\min(i,n-i))) . Delete the element of a sequence at a given index. Return the original sequence if the index is out of range.

deleteAt 2 (a:|[b,c,d]) = a:|[b,d]
deleteAt 4 (a:|[b,c,d]) = deleteAt (-1) (a:|[b,c,d]) = a:|[b,c,d]
valuesplitAt :: Int -> NESeq a -> These (NESeq a) (NESeq a)
#

O(\log(\min(i,n-i))) . Split a sequence at a given position.

  • This ys means that the given position was longer than the length of the list, and ys is the entire original system.

  • That zs means that the given position was zero or smaller, and so zs is the entire original sequence.

  • These ys zs gives ys (the sequence of elements before the given position, take n xs) and zs (the sequence of elements after the given position, drop n xs).

Indexing with predicates

These functions perform sequential searches from the left or right ends of the sequence returning indices of matching elements.

Folds

3 declarations

General folds are available via the Foldable instance of Seq.

Transformations

5 declarations
valuemapWithIndex :: (Int -> a -> b) -> NESeq a -> NESeq b
#

A generalization of fmap, mapWithIndex takes a mapping function that also depends on the element's index, and applies it to every element in the sequence.

valueintersperse :: a -> NESeq a -> NESeq a
#

O(n) . Intersperse an element between the elements of a sequence.

intersperse a empty = empty
intersperse a (singleton x) = singleton x
intersperse a (fromList [x,y]) = fromList [x,a,y]
intersperse a (fromList [x,y,z]) = fromList [x,a,y,a,z]

Zips and unzip

valuezip :: NESeq a -> NESeq b -> NESeq (a, b)
#

O(\min(n_1,n_2)) . zip takes two sequences and returns a sequence of corresponding pairs. If one input is short, excess elements are discarded from the right end of the longer sequence.

valuezipWith :: (a -> b -> c) -> NESeq a -> NESeq b -> NESeq c
#

O(\min(n_1,n_2)) . zipWith generalizes zip by zipping with the function given as the first argument, instead of a tupling function. For example, zipWith (+) is applied to two sequences to take the sequence of corresponding sums.

valuezip3 :: NESeq a -> NESeq b -> NESeq c -> NESeq (a, b, c)
#

O(\min(n_1,n_2,n_3)) . zip3 takes three sequences and returns a sequence of triples, analogous to zip.

valuezipWith3 :: (a -> b -> c -> d) -> NESeq a -> NESeq b -> NESeq c -> NESeq d
#

O(\min(n_1,n_2,n_3)) . zipWith3 takes a function which combines three elements, as well as three sequences and returns a sequence of their point-wise combinations, analogous to zipWith.

valuezip4 :: NESeq a -> NESeq b -> NESeq c -> NESeq d -> NESeq (a, b, c, d)
#

O(\min(n_1,n_2,n_3,n_4)) . zip4 takes four sequences and returns a sequence of quadruples, analogous to zip.

valuezipWith4
  1. :: a -> b -> c -> d -> e
  2. -> NESeq a
  3. -> NESeq b
  4. -> NESeq c
  5. -> NESeq d
  6. -> NESeq e
#

O(\min(n_1,n_2,n_3,n_4)) . zipWith4 takes a function which combines four elements, as well as four sequences and returns a sequence of their point-wise combinations, analogous to zipWith.

valueunzip :: NESeq (a, b) -> (NESeq a, NESeq b)
#

Unzip a sequence of pairs.

unzip ps = ps `seq` (fmap fst ps) (fmap snd ps)

Example:

unzip $ fromList ((1,"a") :| [(2,"b"), (3,"c")]) =
  (fromList (1:|[2,3]), fromList ("a":|["b","c"]))

See the note about efficiency at unzipWith.

valueunzipWith :: (a -> (b, c)) -> NESeq a -> (NESeq b, NESeq c)
#

O(n) . Unzip a sequence using a function to divide elements.

 unzipWith f xs == unzip (fmap f xs)

Efficiency note:

unzipWith produces its two results in lockstep. If you calculate unzipWith f xs and fully force either of the results, then the entire structure of the other one will be built as well. This behavior allows the garbage collector to collect each calculated pair component as soon as it dies, without having to wait for its mate to die. If you do not need this behavior, you may be better off simply calculating the sequence of pairs and using fmap to extract each component sequence.