Vector 用ツール

リストには関数が多数定義されていて便利なのですけれども、速度はVectorにかないません。
そこで Vector を便利に使うための関数を作って集めていきます。

catMaybes を各要素がMaybe型のリストに適用するとNothing の要素は取り除かれ、Just a は a の要素のみになります。

import qualified Data.Vector as V (Vector, null, head, cons, empty, tail)

vCatMaybes :: V.Vector (Maybe a) -> V.Vector a
vCatMaybes vect | V.null vect = V.empty
                | otherwise   = case V.head vect of
                                  Just x  -> x `V.cons` vCatMaybes (V.tail vect)
                                  Nothing -> vCatMaybes (V.tail vect)
-- 同等
vCatMaybes2 = V.foldr (\a acc -> case a of{ Just x->(x `V.cons` acc); Nothing-> acc}) V.empty

{-
*Main Data.Vector> vCatMaybes (V.fromList [Just 1,Nothing,Just 100,Nothing])
-- => fromList [1,100]

*Main Data.Vector> vCatMaybes (V.fromList [Just 1,Nothing])
-- => fromList [1]

*Main Data.Vector> vCatMaybes (V.fromList [Nothing,Nothing])
-- => fromList []

*Main Data.Vector> vCatMaybes (V.fromList [])
-- => fromList []
-}
import qualified Data.Vector as V (Vector, null, head, cons, empty, tail, map, singleton, fromList)

mergesort :: (a -> a -> Ordering) -> V.Vector a -> V.Vector a
mergesort cmp = mergesort' cmp . V.map wrap

mergesort' :: (a -> a -> Ordering) -> V.Vector (V.Vector a) -> V.Vector a
mergesort' cmp vect | V.null   vect        = V.empty
                    | V.null (V.tail vect) = V.head vect
                    | otherwise            = mergesort' cmp (merge_pairs cmp vect)

merge_pairs :: (a -> a -> Ordering) -> V.Vector (V.Vector a) -> V.Vector (V.Vector a)
merge_pairs cmp vect | V.null   vect        = V.empty
                     | V.null (V.tail vect) = vect
                     | otherwise            = merge cmp xs ys `V.cons` merge_pairs cmp xss
                                              where xs   = V.head vect
                                                    rest = V.tail vect
                                                    ys   = V.head rest
                                                    xss  = V.tail rest

merge :: (a -> a -> Ordering) -> V.Vector a -> V.Vector a -> V.Vector a
merge cmp xxs yys | V.null xxs = yys
                  | V.null yys = xxs
                  | otherwise  = let x  = V.head xxs
                                     y  = V.head yys
                                     xs = V.tail xxs
                                     ys = V.tail yys
                                 in case (V.head xxs) `cmp` (V.head yys) of
                                      GT -> y `V.cons` merge cmp xxs ys
                                      _  -> x `V.cons` merge cmp xs  yys

wrap :: a -> V.Vector a
wrap x = V.singleton x

{-
> mergesort compare (V.fromList [9,1,100,5,10,99,2])
-- > fromList [1,2,5,9,10,99,100]

> mergesort compare (V.fromList [9,1])
-- > fromList [1,9]

> mergesort compare (V.fromList [9])
-- > fromList [9]

> mergesort compare (V.fromList [])
-- > fromList []
-}
  • intersperse
import qualified Data.Vector as V (Vector, null, head, cons, empty, tail, map, foldr, (++), fromList)

intersperse :: a -> V.Vector a -> V.Vector a
intersperse sep vect | V.null vect = V.empty
                     | otherwise   = (V.head vect) `V.cons` prependToAll sep (V.tail vect)

prependToAll :: a -> V.Vector a -> V.Vector a
prependToAll sep vect | V.null vect = V.empty
                      | otherwise   = sep `V.cons` ((V.head vect) `V.cons` (prependToAll sep  (V.tail vect)))
  • vGroupBy : groupBy の Vector バージョン。
  • vSpan : span の Vector バージョンです
vGroupBy eq vect | V.null vect = V.empty
                 | otherwise   =  (x `V.cons` ys)  `V.cons`  vGroupBy eq zs
     where (ys,zs) = vSpan (eq x) xs
           x       = V.head vect
           xs      = V.tail vect
{-
> vGroupBy (==) (V.fromList "Mississippi") 
fromList [fromList "M",fromList "i",fromList "ss",fromList "i",fromList "ss",fromList "i",fromList "pp",fromList "i"]
-}

vSpan :: (a -> Bool) -> V.Vector a -> (V.Vector a, V.Vector a)
vSpan p vect | V.null vect     = (V.empty,V.empty)
             | p (V.head vect) =  let (ys,zs) = vSpan p (V.tail vect) in ((V.head vect) `V.cons` ys,zs)
             | otherwise       =  (V.empty,vect)
{-
> vSpan (< 3) (V.fromList [1,2,3,4,1,2,3,4])
-- > (fromList [1,2],fromList [3,4,1,2,3,4])
> vSpan (< 4) (V.fromList [1,2,3,4,1,2,3,4])
-- > (fromList [1,2,3],fromList [4,1,2,3,4])
> vSpan (< 5) (V.fromList [1,2,3,4,1,2,3,4])
-- > (fromList [1,2,3,4,1,2,3,4],fromList [])
> vSpan (< 1) (V.fromList [1,2,3,4,1,2,3,4])
-- > (fromList [],fromList [1,2,3,4,1,2,3,4])

-}