{-# LANGUAGE DeriveTraversable #-}
{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE TypeFamilies #-}
module Purebred.LazyVector
( V
, fromList
, fromChunks
, splitAt
) where
import Data.Bool (otherwise)
import Data.Eq (Eq(..))
import Data.Foldable (Foldable, length)
import Data.Function ((.))
import Data.Functor (Functor)
import Data.Int (Int)
import qualified Data.List as L
import Data.Monoid (Monoid(..))
import Data.Ord (Ord(..))
import Data.Semigroup (Semigroup(..))
import Data.Traversable (Traversable)
import Prelude ((+), (-), uncurry)
import Text.Show (Show)
import qualified Brick.Widgets.List as Brick
import Control.Lens
import qualified Data.Vector as V
newtype V a = V [V.Vector a]
deriving (Functor, Foldable, Traversable, Show)
instance Semigroup (V a) where
V l <> V r = V (l <> r)
instance Monoid (V a) where
mempty = V []
V l `mappend` V r = V (l `mappend` r)
instance Eq a => Eq (V a) where
V l == V r = V.concat l == V.concat r
instance Ord a => Ord (V a) where
V l `compare` V r = V.concat l `compare` V.concat r
instance Brick.Splittable V where
splitAt = splitAt
fromList :: Int -> [a] -> V a
fromList n = V . go
where
go [] = []
go xs = let (h,t) = L.splitAt (max 1 n) xs in V.fromList h : go t
fromChunks :: [V.Vector a] -> V a
fromChunks = V
splitAt :: Int -> V a -> (V a, V a)
splitAt i (V chunks) = case chunks of
[] -> (V [], V [])
(h:t)
| i == length h -> (V [h], V t)
| i < length h ->
let (th, ht) = V.splitAt i h
in (V [th], V (ht : t))
| otherwise ->
let (V h', V t') = splitAt (i - length h) (V t)
in (V (h : h'), V t')
type instance Index (V a) = Int
type instance IxValue (V a) = a
instance Ixed (V a) where
ix n = splitIso (n + 1) . _1 . _VIso . _last . _last
where
splitIso :: Int -> Iso' (V a) (V a, V a)
splitIso i = iso (splitAt i) (uncurry (<>))
_VIso :: Iso' (V a) [V.Vector a]
_VIso = coerced