Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add intersperse #20

Closed
wants to merge 1 commit into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions src/Data/Vector/NonEmpty.hs
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,9 @@
, scanl, scanl', scanl1, scanl1', iscanl, iscanl'
, prescanr, prescanr', postscanr, postscanr'
, scanr, scanr', scanr1, scanr1', iscanr, iscanr'

-- * ??
, intersperse
) where


Expand All @@ -191,7 +194,7 @@

import qualified Data.Foldable as Foldable
import Data.Either (Either(..))
import Data.Functor hiding (unzip)

Check warning on line 197 in src/Data/Vector/NonEmpty.hs

View workflow job for this annotation

GitHub Actions / build (ubuntu-latest, 8.10)

Module ‘Data.Functor’ does not export ‘unzip’

Check warning on line 197 in src/Data/Vector/NonEmpty.hs

View workflow job for this annotation

GitHub Actions / build (ubuntu-latest, 8.10)

Module ‘Data.Functor’ does not export ‘unzip’

Check warning on line 197 in src/Data/Vector/NonEmpty.hs

View workflow job for this annotation

GitHub Actions / build (ubuntu-latest, 9.0)

Module ‘Data.Functor’ does not export ‘unzip’

Check warning on line 197 in src/Data/Vector/NonEmpty.hs

View workflow job for this annotation

GitHub Actions / build (ubuntu-latest, 9.0)

Module ‘Data.Functor’ does not export ‘unzip’

Check warning on line 197 in src/Data/Vector/NonEmpty.hs

View workflow job for this annotation

GitHub Actions / build (ubuntu-latest, 9.2)

Module ‘Data.Functor’ does not export ‘unzip’

Check warning on line 197 in src/Data/Vector/NonEmpty.hs

View workflow job for this annotation

GitHub Actions / build (ubuntu-latest, 9.2)

Module ‘Data.Functor’ does not export ‘unzip’

Check warning on line 197 in src/Data/Vector/NonEmpty.hs

View workflow job for this annotation

GitHub Actions / build (ubuntu-latest, 9.4)

Module ‘Data.Functor’ does not export ‘unzip’

Check warning on line 197 in src/Data/Vector/NonEmpty.hs

View workflow job for this annotation

GitHub Actions / build (ubuntu-latest, 9.4)

Module ‘Data.Functor’ does not export ‘unzip’

Check warning on line 197 in src/Data/Vector/NonEmpty.hs

View workflow job for this annotation

GitHub Actions / build (ubuntu-latest, 9.6)

Module ‘Data.Functor’ does not export ‘unzip’

Check warning on line 197 in src/Data/Vector/NonEmpty.hs

View workflow job for this annotation

GitHub Actions / build (ubuntu-latest, 9.6)

Module ‘Data.Functor’ does not export ‘unzip’

Check warning on line 197 in src/Data/Vector/NonEmpty.hs

View workflow job for this annotation

GitHub Actions / build (macOS-latest, latest)

Module ‘Data.Functor’ does not export ‘unzip’

Check warning on line 197 in src/Data/Vector/NonEmpty.hs

View workflow job for this annotation

GitHub Actions / build (macOS-latest, latest)

Module ‘Data.Functor’ does not export ‘unzip’

Check warning on line 197 in src/Data/Vector/NonEmpty.hs

View workflow job for this annotation

GitHub Actions / bounds-checking

Module ‘Data.Functor’ does not export ‘unzip’
import Data.Int
import Data.List.NonEmpty (NonEmpty(..))
import qualified Data.List.NonEmpty as NonEmpty
Expand Down Expand Up @@ -2646,3 +2649,17 @@
iscanr' :: (Int -> a -> b -> b) -> b -> NonEmptyVector a -> NonEmptyVector b
iscanr' f b = NonEmptyVector . V.iscanr' f b . _neVec
{-# INLINE iscanr' #-}

-- | \(\mathcal{O}(n)\). The 'intersperse' function takes an element and a NonEmptyVector
Copy link
Owner

@emilypi emilypi Nov 13, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like you copypasted something like the implementation for intersperse from Data.List.NonEmpty, which isn't a very good implementation for something like vector or nonempty-vector for several reasons:

  1. This function is not O(n): cons for Vector is O(n), and vector consing for n-1-many elements is actually O(n^2). This makes the implementation rather unsatisfactory, and in fact, worse than the just converting to and from a list for very large vectors.

  2. There is an issue out to resolve the suboptimal vector cons-based implementation (posted here: Adding intersperse to the API haskell/vector#421), which discusses the potential streams-based implementation that I would welcome in this package when the time comes for that work to be done in vector. Otherwise, we'd be importing a very suboptimal implementation into this package, breaking from vector's API. Presumably such a streams-based implementation could amortize away some of the array resizing needed under the hood so we don't have to take the quadratic hit so hard.

  3. I think there's benefit in matching the vector API, since it makes this package a near drop-in replacement for vector, minus some fiddling and pattern matching to enforce the nonempty invariants in one's code. We'd be deviating from that until point 2 is implemented.

So i have to reject this on those grounds.

Copy link
Owner

@emilypi emilypi Nov 13, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At least, in its current incarnation. If you want to help the vector package move the work along for intersperse, I'm happy to keep this open and accept it with a deference to the vector implementation!

-- and \`intersperses\' that element between the elements of the NonEmptyVector.
--
intersperse :: a -> NonEmptyVector a -> NonEmptyVector a
intersperse sep vne =
let (h, t) = uncons vne
in consV h (prependToAll sep t)
{-# INLINE intersperse #-}

prependToAll :: a -> Vector a -> Vector a
prependToAll sep vec = case V.uncons vec of
Nothing -> V.empty
Just (h, t) -> V.cons sep (V.cons h (prependToAll sep t))
Loading