diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,30 @@
+Copyright Florian Hofmann (c) 2016
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+
+    * Neither the name of Florian Hofmann nor the names of other
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,2 @@
+import Distribution.Simple
+main = defaultMain
diff --git a/src/Data/Vector/Split.hs b/src/Data/Vector/Split.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Vector/Split.hs
@@ -0,0 +1,124 @@
+
+
+
+module Data.Vector.Split
+  ( chunksOf
+  , splitPlaces
+  , splitPlacesBlanks
+  , chop
+  , divvy
+  , module Data.Vector.Split.Internal
+  ) where
+
+
+import           Data.Vector.Generic (Vector)
+import qualified Data.Vector.Generic as V
+
+import           Data.List (unfoldr)
+
+import           Data.Vector.Split.Internal
+
+
+
+-- | @'chunksOf' n@ splits a vector into length-n pieces.  The last
+--   piece will be shorter if @n@ does not evenly divide the length of
+--   the vector.  If @n <= 0@, @'chunksOf' n l@ returns an infinite list
+--   of empty vectors.  For example:
+--
+--   Note that @'chunksOf' n []@ is @[]@, not @[[]]@.  This is
+--   intentional, and is consistent with a recursive definition of
+--   'chunksOf'; it satisfies the property that
+--
+--   @chunksOf n xs ++ chunksOf n ys == chunksOf n (xs ++ ys)@
+--
+--   whenever @n@ evenly divides the length of @xs@.
+chunksOf :: Vector v a => Int -> v a -> [v a]
+chunksOf i = unfoldr go
+  where go v | V.null v = Nothing
+             | otherwise = Just (V.splitAt i v)
+
+-- | Split a vector into chunks of the given lengths. For example:
+--
+-- > splitPlaces [2,3,4] [1..20] == [[1,2],[3,4,5],[6,7,8,9]]
+-- > splitPlaces [4,9] [1..10] == [[1,2,3,4],[5,6,7,8,9,10]]
+-- > splitPlaces [4,9,3] [1..10] == [[1,2,3,4],[5,6,7,8,9,10]]
+--
+--   If the input vector is longer than the total of the given lengths,
+--   then the remaining elements are dropped. If the vector is shorter
+--   than the total of the given lengths, then the result may contain
+--   fewer chunks than requested, and the last chunk may be shorter
+--   than requested.
+splitPlaces :: Vector v a => [Int] -> v a -> [v a]
+splitPlaces is v = unfoldr go (is,v)
+  where go ([],_)   = Nothing
+        go (i:is,v) | V.null v = Nothing
+                    | otherwise = let (l,r) = V.splitAt i v in Just (l,(is,r))
+
+
+-- | Split a vector into chunks of the given lengths. Unlike
+--   'splitPlaces', the output list will always be the same length as
+--   the first input argument. If the input vector is longer than the
+--   total of the given lengths, then the remaining elements are
+--   dropped. If the vector is shorter than the total of the given
+--   lengths, then the last several chunks will be shorter than
+--   requested or empty. For example:
+--
+-- > splitPlacesBlanks [2,3,4] [1..20] == [[1,2],[3,4,5],[6,7,8,9]]
+-- > splitPlacesBlanks [4,9] [1..10] == [[1,2,3,4],[5,6,7,8,9,10]]
+-- > splitPlacesBlanks [4,9,3] [1..10] == [[1,2,3,4],[5,6,7,8,9,10],[]]
+--
+--   Notice the empty list in the output of the third example, which
+--   differs from the behavior of 'splitPlaces'.
+splitPlacesBlanks :: Vector v a => [Int] -> v a -> [v a]
+splitPlacesBlanks is v = unfoldr go (is,v)
+  where go ([],_)   = Nothing
+        go (i:is,v) = let (l,r) = V.splitAt i v in Just (l,(is,r))
+
+
+
+-- | A useful recursion pattern for processing a list to produce a new
+--   list, often used for \"chopping\" up the input list.  Typically
+--   chop is called with some function that will consume an initial
+--   prefix of the list and produce a value and the rest of the list.
+--
+--   For example, many common Prelude functions can be implemented in
+--   terms of @chop@:
+--
+-- > group :: (Eq a) => [a] -> [[a]]
+-- > group = chop (\ xs@(x:_) -> span (==x) xs)
+-- >
+-- > words :: String -> [String]
+-- > words = filter (not . null) . chop (span (not . isSpace) . dropWhile isSpace)
+chop :: Vector v a => (v a -> (b, v a)) -> v a -> [b]
+chop f v | V.null v  = []
+         | otherwise = b : chop f v'
+            where (b, v') = f v
+
+-- | Divides up an input vector into a set of subvectors, according to 'n' and 'm'
+--   input specifications you provide. Each subvector will have 'n' items, and the
+--   start of each subvector will be offset by 'm' items from the previous one.
+--
+-- > divvy 5 5 [1..20] == [[1,2,3,4,5],[6,7,8,9,10],[11,12,13,14,15],[16,17,18,19,20]]
+--
+--   In the case where a source vector's trailing elements do no fill an entire
+--   subvector, those trailing elements will be dropped.
+--
+-- > divvy 5 2 [1..10] == [[1,2,3,4,5],[3,4,5,6,7],[5,6,7,8,9]]
+--
+--   As an example, you can generate a moving average over a vector of prices:
+-- 
+-- > type Prices = [Float]
+-- > type AveragePrices = [Float]
+-- > 
+-- > average :: [Float] -> Float
+-- > average xs = sum xs / (fromIntegral $ length xs)
+-- > 
+-- > simpleMovingAverage :: Prices -> AveragePrices
+-- > simpleMovingAverage priceList =
+-- >   map average divvyedPrices
+-- >     where divvyedPrices = divvy 20 1 priceList
+divvy :: Vector v a => Int -> Int -> v a -> [v a]
+divvy n m v | V.null v = []
+            | otherwise = filter (\ws -> n == V.length ws)
+                        . chop (\xs -> (V.take n xs, V.drop m xs))
+                        $ v
diff --git a/src/Data/Vector/Split/Internal.hs b/src/Data/Vector/Split/Internal.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Vector/Split/Internal.hs
@@ -0,0 +1,338 @@
+
+
+
+module Data.Vector.Split.Internal 
+  ( split
+  , Splitter(..)
+  , splitOn
+  , splitOneOf
+  , splitWhen
+  , endBy
+  , oneOf
+  , endByOneOf
+  , wordsBy
+  , linesBy
+  , onSublist
+  , whenElt
+  , dropDelims
+  , keepDelimsL
+  , keepDelimsR
+  , condense
+  , dropInitBlank
+  , dropInnerBlanks
+  , dropFinalBlank
+  , dropBlanks
+  , startsWith
+  , startsWithOneOf
+  , endsWith
+  , endsWithOneOf
+  ) where
+
+
+import           Data.Vector.Generic (Vector)
+import qualified Data.Vector.Generic as V
+
+import qualified Data.Vector as BV
+
+import qualified Data.List as L
+
+-- | A delimiter is a list of predicates on elements, matched by some
+--   contiguous subsequence of a list.
+newtype Delimiter a = Delimiter (BV.Vector (a -> Bool))
+
+-- | Try to match a delimiter at the start of a list, either failing
+--   or decomposing the list into the portion which matched the delimiter
+--   and the remainder.
+matchDelim :: Vector v a => Delimiter a -> v a -> Maybe (v a, v a)
+matchDelim (Delimiter ds) xs = if match && lengthOk then Just (V.splitAt (V.length ds) xs) else Nothing
+    where match = V.and $ V.zipWith ($) ds (V.convert xs)
+          lengthOk = V.length ds <= V.length xs
+
+
+
+
+data Chunk v a = Delim (v a) | Text (v a)
+    deriving (Show, Eq)
+
+
+fromChunk :: Chunk v a -> v a
+fromChunk (Delim d) = d
+fromChunk (Text  t) = t
+
+isDelim :: Chunk v a -> Bool
+isDelim (Delim _) = True
+isDelim (Text  _) = False
+
+type SplitList v a = [Chunk v a]
+
+type Splitter v a = v a -> SplitList v a
+
+
+
+
+toSplitList :: Vector v a => Delimiter a -> v a -> SplitList v a
+toSplitList d v = go 0
+    where go i | i < V.length v = case matchDelim d (V.drop i v) of
+                                      Just (l,r) -> Text (V.take i v) : Delim l : toSplitList d r
+                                      Nothing    -> go (i+1)
+               | otherwise      = [Text v]
+
+
+split :: Vector v a => Splitter v a -> v a -> [v a]
+split s v = map go $ s v
+    where go (Text t)  = t
+          go (Delim d) = d
+
+
+-- Convenience functions
+
+-- | Split on the given sublist. Equivalent to split . dropDelims . onSublist. For example:
+--
+-- >>> splitOn (BV.fromList "..") (BV.fromList "a..b...c....d..")
+-- ["a","b",".c","","d",""]
+-- 
+-- In some parsing combinator frameworks this is also known as sepBy.
+--
+-- Note that this is the right inverse of the intercalate function from Data.List, that is,
+--
+-- >> \xs -> (intercalate xs . splitOn xs) === id
+--
+-- splitOn x . intercalate x is the identity on certain lists, but it is
+-- tricky to state the precise conditions under which this holds. (For
+-- example, it is not enough to say that x does not occur in any elements
+-- of the input list. Working out why is left as an exercise for the
+-- reader.)
+splitOn :: (Vector v a, Eq a) => v a -> v a -> [v a]
+splitOn xs = split (dropDelims . onSublist xs)
+
+-- | Split on any of the given elements. Equivalent to split . dropDelims . oneOf. For example:
+--
+-- >>> splitOneOf (BV.fromList ";.,") (BV.fromList "foo,bar;baz.glurk")
+-- ["foo","bar","baz","glurk"]
+splitOneOf :: (Vector v a, Eq a) => v a -> v a -> [v a]
+splitOneOf xs = split (dropDelims . oneOf xs)
+
+-- | Split on elements satisfying the given predicate. Equivalent to split . dropDelims . whenElt. For example:
+--
+-- >>> splitWhen (<0) (BV.fromList [1,3,-4,5,7,-9,0,2])
+-- [[1,3],[5,7],[0,2]]
+splitWhen :: (Vector v a) => (a -> Bool) -> v a -> [v a]
+splitWhen p = split (dropDelims . whenElt p)
+
+-- | Split into chunks terminated by the given subsequence. Equivalent to split . dropFinalBlank . dropDelims . onSublist. For example:
+--
+-- >>> endBy (BV.fromList ";") (BV.fromList "foo;bar;baz;")
+-- ["foo","bar","baz"]
+--
+-- Note also that the lines function from Data.List is equivalent to endBy "\n".
+endBy :: (Vector v a, Eq a) => v a -> v a -> [v a]
+endBy xs = split (dropFinalBlank . dropDelims . onSublist xs)
+-- Basic Strategies
+
+-- | A splitting strategy that splits on any one of the given elements. For example:
+-- >>> split (oneOf (BV.fromList "xyz")) (BV.fromList "aazbxyzcxd")
+-- ["aa","z","b","x","","y","","z","c","x","d"]
+oneOf :: (Vector v a, Eq a) => v a -> Splitter v a
+oneOf xs = toSplitList delim
+    where delim = Delimiter (BV.singleton (`V.elem` xs))
+
+
+-- | Split into chunks terminated by one of the given elements. Equivalent to split . dropFinalBlank . dropDelims . oneOf. For example:
+--
+-- >>> endByOneOf (BV.fromList ";,") (BV.fromList "foo;bar,baz;") 
+-- ["foo","bar","baz"]
+endByOneOf :: (Vector v a, Eq a) => v a -> v a -> [v a]
+endByOneOf xs = split (dropFinalBlank . dropDelims . oneOf xs)
+
+
+-- | Split into "words", with word boundaries indicated by the given predicate. Satisfies words === wordsBy isSpace; equivalent to split . dropBlanks . dropDelims . whenElt. For example:
+--
+-- >>> wordsBy (=='x') (BV.fromList "dogxxxcatxbirdxx") 
+-- ["dog","cat","bird"]
+wordsBy :: Vector v a => (a -> Bool) -> v a -> [v a]
+wordsBy p = split (dropBlanks . dropDelims . whenElt p)
+
+
+-- | Split into "lines", with line boundaries indicated by the given predicate. Satisfies lines === linesBy (=='\n'); equivalent to split . dropFinalBlank . dropDelims . whenElt. For example:
+--
+-- >>> linesBy (=='x') (BV.fromList "dogxxxcatxbirdxx")
+-- ["dog","","","cat","bird",""]
+linesBy :: Vector v a => (a -> Bool) -> v a -> [v a]
+linesBy p = split (dropFinalBlank . dropDelims . whenElt p)
+
+
+-- | A splitting strategy that splits on the given list, when it is
+-- encountered as an exact subsequence. For example:
+--
+-- >>> split (onSublist (BV.fromList "xyz")) (BV.fromList "aazbxyzcxd")
+-- ["aazb","xyz","cxd"]
+--
+-- Note that splitting on the empty list is not allowed in `vector-split`.
+-- This is a major difference between `split` and `vector-split`. In any
+-- case nobody should use `vector-split` to do this anyway.
+onSublist :: (Vector v a, Eq a) => v a -> Splitter v a
+onSublist xs = toSplitList delim
+    where delim = Delimiter (V.map (==) . V.convert $ xs)
+
+-- | A splitting strategy that splits on any elements that satisfy the given predicate. For example:
+--
+-- >>> split (whenElt (<0)) (BV.fromList [2,4,-3,6,-9,1])
+-- [[2,4],[-3],[6],[-9],[1]]
+whenElt :: (Vector v a) => (a -> Bool) -> Splitter v a
+whenElt p = toSplitList delim
+    where delim = Delimiter (V.singleton p)
+
+
+-- Strategy Transformers
+
+-- | Drop delimiters from the output (the default is to keep them). For example,
+--
+-- >>> split (oneOf (BV.fromList ":")) (BV.fromList "a:b:c")
+-- ["a",":","b",":","c"]
+-- >>> split (dropDelims . oneOf (BV.fromList ":")) (BV.fromList "a:b:c")
+-- ["a","b","c"]
+dropDelims :: Vector v a => SplitList v a -> SplitList v a
+dropDelims = filter go 
+    where go (Delim _) = False
+          go (Text _ ) = True
+
+-- | Keep delimiters in the output by prepending them to adjacent chunks. For example:
+--
+-- >>> split (keepDelimsL . oneOf (BV.fromList "xyz")) (BV.fromList "aazbxyzcxd")
+-- ["aa","zb","x","y","zc","xd"]
+keepDelimsL :: Vector v a => SplitList v a -> SplitList v a
+keepDelimsL (Delim d : Text t : rst) = Text (d V.++ t) : keepDelimsL rst
+keepDelimsL (rs : rst)               = rs : keepDelimsL rst
+keepDelimsL []                       = []
+
+-- | Keep delimiters in the output by appending them to adjacent chunks. For example:
+--
+-- >>> split (keepDelimsR . oneOf (BV.fromList "xyz")) (BV.fromList "aazbxyzcxd")
+-- ["aaz","bx","y","z","cx","d"]
+keepDelimsR :: Vector v a => SplitList v a -> SplitList v a
+keepDelimsR (Text t : Delim d : rst) = Text (t V.++ d) : keepDelimsR rst
+keepDelimsR (rs : rst)               = rs : keepDelimsR rst
+keepDelimsR []                       = []
+
+-- FIXME really not sure about the delim : text : delim case ... 
+-- this was inserted to be compatible with the split package
+
+-- | Condense multiple consecutive delimiters into one. For example:
+--
+-- >>> split (condense . oneOf (BV.fromList "xyz")) (BV.fromList "aazbxyzcxd")
+-- ["aa","z","b","xyz","c","x","d"]
+-- >>> split (dropDelims . oneOf (BV.fromList "xyz")) (BV.fromList "aazbxyzcxd")
+-- ["aa","b","","","c","d"]
+-- >>> split (condense . dropDelims . oneOf (BV.fromList "xyz")) (BV.fromList "aazbxyzcxd")
+-- ["aa","b","c","d"]
+--
+-- FIXME this function is not fully compatible with the Data.List.Split version.
+condense :: Vector v a => SplitList v a -> SplitList v a
+condense (Delim a : Delim b : rst) = condense (Delim (a V.++ b) : rst)
+condense (Delim a : Text t : Delim b : rst) | V.null t = condense (Delim (a V.++ b) : rst)
+condense (t : rst) = t : condense rst
+condense []                        = []
+
+-- | Don't generate a blank chunk if there is a delimiter at the beginning. For example:
+--
+-- >>> split (oneOf (BV.fromList ":")) (BV.fromList ":a:b")
+-- ["",":","a",":","b"]
+-- >>> split (dropInitBlank . oneOf (BV.fromList ":")) (BV.fromList ":a:b")
+-- [":","a",":","b"]
+dropInitBlank :: Vector v a => SplitList v a -> SplitList v a
+dropInitBlank (Text t : rst) | V.null t = rst
+dropInitBlank rst                       = rst
+
+-- | Don't generate a blank chunk if there is a delimiter at the end. For example:
+--
+-- split (oneOf (BV.fromList ":")) (BV.fromList "a:b:")
+-- ["a",":","b",":",""]
+-- split (dropFinalBlank . oneOf (BV.fromList ":")) (BV.fromList "a:b:")
+-- ["a",":","b",":"]
+dropFinalBlank :: Vector v a => SplitList v a -> SplitList v a
+dropFinalBlank [Text t]         | V.null t = []
+dropFinalBlank (rs : rst)       = rs : dropFinalBlank rst
+dropFinalBlank []               = []
+
+-- | Don't generate blank chunks between consecutive delimiters. For example:
+--
+-- >>> split (oneOf (BV.fromList ":")) (BV.fromList "::b:::a")
+-- ["",":","",":","b",":","",":","",":","a"]
+-- >>> split (dropInnerBlanks . oneOf (BV.fromList ":")) (BV.fromList "::b:::a")
+-- ["",":",":","b",":",":",":","a"]
+dropInnerBlanks :: Vector v a => SplitList v a -> SplitList v a
+dropInnerBlanks (Text a : rst) = Text a : dropInnerBlanksGo rst
+dropInnerBlanks rst            = dropInnerBlanksGo rst
+
+dropInnerBlanksGo :: Vector v a => [Chunk v a] -> [Chunk v a]
+dropInnerBlanksGo [Text a]                  = [Text a]
+dropInnerBlanksGo (Text a : rst) | V.null a = dropInnerBlanksGo rst
+dropInnerBlanksGo (chunk  : rst)            = chunk : dropInnerBlanksGo rst
+dropInnerBlanksGo []                        = []
+
+
+-- Derived combinators
+
+-- | Drop all blank chunks from the output, and condense consecutive
+-- delimiters into one. 
+-- Equivalent to dropInitBlank . dropFinalBlank . condense. For example:
+--
+-- >>> split (oneOf (BV.fromList ":")) (BV.fromList "::b:::a")
+-- ["",":","",":","b",":","",":","",":","a"]
+-- >>> split (dropBlanks . oneOf (BV.fromList ":")) (BV.fromList "::b:::a")
+-- ["::","b",":::","a"]
+dropBlanks :: Vector v a => SplitList v a -> SplitList v a
+dropBlanks = condense . filter go
+    where go (Text t) | V.null t = False
+          go _                   = True
+
+-- | Make a strategy that splits a list into chunks that all start with the
+-- given subsequence (except possibly the first). Equivalent to
+-- dropInitBlank . keepDelimsL . onSublist. For example:
+--
+-- >>> split (startsWith (BV.fromList "app")) (BV.fromList "applyapplicativeapplaudapproachapple")
+-- ["apply","applicative","applaud","approach","apple"]
+startsWith :: (Vector v a, Eq a) => v a -> Splitter v a
+startsWith xs = dropInitBlank . keepDelimsL . onSublist xs
+
+-- | Make a strategy that splits a list into chunks that all start with one
+-- of the given elements (except possibly the first). Equivalent to
+-- dropInitBlank . keepDelimsL . oneOf. For example:
+--
+-- >>> split (startsWithOneOf (BV.fromList ['A'..'Z'])) (BV.fromList "ACamelCaseIdentifier")
+-- ["A","Camel","Case","Identifier"]
+startsWithOneOf :: (Vector v a, Eq a) => v a -> Splitter v a
+startsWithOneOf xs = dropInitBlank . keepDelimsL . oneOf xs
+
+-- | Make a strategy that splits a list into chunks that all end with the
+-- given subsequence, except possibly the last. Equivalent to
+-- dropFinalBlank . keepDelimsR . onSublist. For example:
+--
+-- >>> split (endsWith (BV.fromList "ly")) (BV.fromList "happilyslowlygnarlylily")
+-- ["happily","slowly","gnarly","lily"]
+endsWith :: (Vector v a, Eq a) => v a -> Splitter v a
+endsWith xs = dropFinalBlank . keepDelimsR . onSublist xs
+
+
+
+-- Note: this function is not consistent with the Data.List.Split version
+
+-- | Make a strategy that splits a list into chunks that all end with one of
+-- the given elements, except possibly the last. Equivalent to
+-- dropFinalBlank . keepDelimsR . oneOf. For example:
+--
+-- >>> split (condense . endsWithOneOf (BV.fromList ".,?! ")) (BV.fromList "Hi, there!  How are you?")
+-- ["Hi, ","there!  ","How ","are ","you?"]
+endsWithOneOf :: (Vector v a, Eq a) => v a -> Splitter v a
+endsWithOneOf xs = dropFinalBlank . keepDelimsR . oneOf xs
+
+
+
+
+
+-- Util
+
+intercalateV :: Vector v a => v a -> [v a] -> v a
+intercalateV d = go
+    where go [x]    = x
+          go (x:xs) = x V.++ d V.++ go xs
diff --git a/test/Spec.hs b/test/Spec.hs
new file mode 100644
--- /dev/null
+++ b/test/Spec.hs
@@ -0,0 +1,183 @@
+
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE CPP #-}
+
+import           Test.Tasty
+import qualified Test.Tasty.QuickCheck as QC
+
+import           Test.QuickCheck
+import           Test.QuickCheck.Function
+
+import qualified Data.Vector as V
+import qualified Data.Vector.Split as V
+import qualified Data.Vector.Split.Internal as V
+
+import qualified Data.List       as L
+import qualified Data.List.Split as L
+
+import           Data.Char
+
+import           Debug.Trace
+
+main :: IO ()
+main = defaultMain tests
+
+
+
+tests = testGroup "tests" 
+  [ testGroup "basic strategies"
+    [ QC.testProperty "oneOf" prop_oneOf
+    , QC.testProperty "onSublist" prop_onSublist
+    , QC.testProperty "whenElt" prop_whenElt
+    ]
+  , testGroup "strategy transformers"
+    [ QC.testProperty "dropDelims" prop_dropDelims
+    , QC.testProperty "keepDelimsL" prop_keepDelimsL
+    , QC.testProperty "keepDelimsR" prop_keepDelimsR
+    , QC.testProperty "condense" prop_condense
+    , QC.testProperty "dropInitBlank" prop_dropInitBlank
+    , QC.testProperty "dropFinalBlank" prop_dropFinalBlank
+    , QC.testProperty "dropInnerBlank" prop_dropInnerBlank
+    ]
+  , testGroup "other splitting methods"
+    [ QC.testProperty "chunksOf" prop_chunksOf
+    , QC.testProperty "splitPlaces" prop_splitPlaces
+    , QC.testProperty "splitPlacesBlanks" prop_splitPlacesBlanks
+    , QC.testProperty "chop" prop_chop
+    , QC.testProperty "chopGroup" prop_chopGroup
+#if MIN_VERSION_split(2,3,0)
+    , QC.testProperty "divvy" prop_divvy
+#endif
+    ]
+  , testGroup "convenience functions"
+    [ QC.testProperty "splitOn" prop_splitOn
+    , QC.testProperty "splitOneOf" prop_splitOneOf
+    , QC.testProperty "splitWhen" prop_splitWhen
+    , QC.testProperty "endBy" prop_endBy
+    , QC.testProperty "endByOneOf" prop_endByOneOf
+    , QC.testProperty "wordsBy" prop_wordsBy
+    , QC.testProperty "linesBy" prop_linesBy
+    ]
+  ]
+
+-- small set of elements used for testing
+
+newtype Elt = Elt { unElt :: Char } deriving (Eq)
+
+type Elements = [Elt]
+type SomeElements = NonEmptyList Elt
+
+instance Show Elt where
+    show (Elt c) = show c
+
+instance Arbitrary Elt where
+    arbitrary = elements (map Elt "abcde")
+
+instance CoArbitrary Elt where
+  coarbitrary = coarbitrary . ord . unElt
+
+
+instance Function Elt where
+  function = functionMap unElt Elt
+
+-- Basic Strategies
+
+prop_oneOf :: Elements -> Elements -> Property
+prop_oneOf d = listVsVec (L.split (L.oneOf d)) (V.split (V.oneOf (V.fromList d)))
+
+prop_onSublist :: SomeElements -> Elements -> Property
+prop_onSublist (NonEmpty d) = listVsVec (L.split (L.onSublist d)) (V.split (V.onSublist (V.fromList d)))
+
+prop_whenElt :: Fun Elt Bool -> Elements -> Property
+prop_whenElt (Fun _ f) = listVsVec (L.split (L.whenElt f)) (V.split (V.whenElt f))
+
+
+
+-- Strategy Transformers
+
+prop_dropDelims :: SomeElements -> Elements -> Property
+prop_dropDelims (NonEmpty d) = listVsVec (L.split (L.dropDelims (L.oneOf d)))
+                                         (V.split (V.dropDelims . V.oneOf (V.fromList d)))
+
+prop_keepDelimsL :: SomeElements -> Elements -> Property
+prop_keepDelimsL (NonEmpty d) = listVsVec (L.split (L.keepDelimsL (L.oneOf d)))
+                                          (V.split (V.keepDelimsL . V.oneOf (V.fromList d)))
+
+prop_keepDelimsR :: SomeElements -> Elements -> Property
+prop_keepDelimsR (NonEmpty d) = listVsVec (L.split (L.keepDelimsR (L.oneOf d)))
+                                          (V.split (V.keepDelimsR . V.oneOf (V.fromList d)))
+
+prop_condense :: SomeElements -> Elements -> Property
+prop_condense (NonEmpty d) = listVsVec (L.split (L.condense (L.oneOf d)))
+                                       (V.split (V.condense . V.oneOf (V.fromList d)))
+
+prop_dropInitBlank :: SomeElements -> Elements -> Property
+prop_dropInitBlank (NonEmpty d) = listVsVec (L.split (L.dropInitBlank (L.oneOf d)))
+                                            (V.split (V.dropInitBlank . V.oneOf (V.fromList d)))
+
+prop_dropFinalBlank :: SomeElements -> Elements -> Property
+prop_dropFinalBlank (NonEmpty d) = listVsVec (L.split (L.dropFinalBlank (L.oneOf d)))
+                                             (V.split (V.dropFinalBlank . V.oneOf (V.fromList d)))
+
+prop_dropInnerBlank :: SomeElements -> Elements -> Property
+prop_dropInnerBlank (NonEmpty d) = listVsVec (L.split (L.dropInnerBlanks (L.oneOf d)))
+                                             (V.split (V.dropInnerBlanks . V.oneOf (V.fromList d)))
+
+-- Other Splitting Methods
+
+prop_chunksOf :: Positive Int -> [Double] -> Property
+prop_chunksOf (Positive i) = listVsVec (L.chunksOf i) (V.chunksOf i)
+
+prop_splitPlaces :: [Positive Int] -> [Double] -> Property
+prop_splitPlaces is = listVsVec (L.splitPlaces is') (V.splitPlaces is')
+    where is' = map getPositive is
+
+prop_splitPlacesBlanks :: [Positive Int] -> [Double] -> Property
+prop_splitPlacesBlanks is = listVsVec (L.splitPlacesBlanks is') (V.splitPlacesBlanks is')
+    where is' = map getPositive is
+
+prop_chop :: [Double] -> Property
+prop_chop = listVsVec (L.chop (L.splitAt 10)) (V.chop (V.splitAt 10))
+
+prop_chopGroup :: [Double] -> Property
+prop_chopGroup = listVsVec (L.chop (\xs -> L.span (== L.head xs) xs)) (V.chop (\xs -> V.span (== V.head xs) xs))
+
+#if MIN_VERSION_split(2,3,0)
+prop_divvy :: Positive Int -> Positive Int -> [Double] -> Property
+prop_divvy (Positive n) (Positive m) = listVsVec (L.divvy n m) (V.divvy n m)
+#endif
+
+
+
+-- Convenience functions
+
+prop_splitOneOf :: SomeElements -> Elements -> Property
+prop_splitOneOf (NonEmpty ds) = listVsVec (L.splitOneOf ds) (V.splitOneOf (V.fromList ds))
+
+prop_splitOn :: SomeElements -> Elements -> Property
+prop_splitOn (NonEmpty ds) = listVsVec (L.splitOn ds) (V.splitOn (V.fromList ds))
+
+prop_splitWhen :: Fun Elt Bool -> Elements -> Property
+prop_splitWhen (Fun _ f) = listVsVec (L.splitWhen f) (V.splitWhen f)
+
+prop_endBy :: SomeElements -> Elements -> Property
+prop_endBy (NonEmpty p) = listVsVec (L.endBy p) (V.endBy (V.fromList p))
+
+prop_endByOneOf :: SomeElements -> Elements -> Property
+prop_endByOneOf (NonEmpty p) = listVsVec (L.endByOneOf p) (V.endByOneOf (V.fromList p))
+
+prop_wordsBy :: Fun Elt Bool -> Elements -> Property
+prop_wordsBy (Fun _ f) = listVsVec (L.wordsBy f) (V.wordsBy f)
+
+prop_linesBy :: Fun Elt Bool -> Elements -> Property
+prop_linesBy (Fun _ f) = listVsVec (L.linesBy f) (V.linesBy f)
+
+
+
+
+-- | compare a list splitting vs a vector splitting function
+listVsVec :: (Show a, Eq a) => ([a] -> [[a]]) -> (V.Vector a -> [V.Vector a]) -> [a] -> Property
+listVsVec a b l = ls === map V.toList vs
+    where v = V.fromList l
+          ls = a l
+          vs = b v
diff --git a/vector-split.cabal b/vector-split.cabal
new file mode 100644
--- /dev/null
+++ b/vector-split.cabal
@@ -0,0 +1,49 @@
+name:                vector-split
+version:             1.0.0.0
+synopsis:            Initial project template from stack
+description:         Please see README.md
+homepage:            https://github.com/fhaust/vector-split#readme
+license:             BSD3
+license-file:        LICENSE
+author:              Florian Hofmann
+maintainer:          fho@f12n.de
+copyright:           MIT
+category:            Web
+build-type:          Simple
+-- extra-source-files:
+cabal-version:       >=1.10
+
+library
+  hs-source-dirs:      src
+  exposed-modules:     Data.Vector.Split
+                     , Data.Vector.Split.Internal
+  build-depends:       base     >= 4    && < 5
+                     , vector   >= 0.10 && < 0.12
+  default-language:    Haskell2010
+  ghc-options:         -Wall
+
+--executable vector-split-exe
+--  hs-source-dirs:      app
+--  main-is:             Main.hs
+--  ghc-options:         -threaded -rtsopts -with-rtsopts=-N
+--  build-depends:       base
+--                     , vector-split
+--  default-language:    Haskell2010
+
+test-suite vector-split-test
+  type:                exitcode-stdio-1.0
+  hs-source-dirs:      test
+  main-is:             Spec.hs
+  build-depends:       base
+                     , vector
+                     , vector-split
+                     , split
+                     , tasty
+                     , tasty-quickcheck
+                     , QuickCheck
+  ghc-options:         -threaded -rtsopts -with-rtsopts=-N
+  default-language:    Haskell2010
+
+source-repository head
+  type:     git
+  location: https://github.com/fhaust/vector-split
