{-# LANGUAGE CPP #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeFamilies #-}
module Data.Vec.Pull (
Vec (..),
empty,
singleton,
toList,
fromList,
_Vec,
fromListPrefix,
reifyList,
(!),
ix,
_Cons,
_head,
_tail,
head,
tail,
foldMap,
foldMap1,
ifoldMap,
ifoldMap1,
foldr,
ifoldr,
foldl',
length,
null,
sum,
product,
map,
imap,
zipWith,
izipWith,
bind,
join,
universe,
) where
import Prelude ()
import Prelude.Compat
(Bool (..), Eq (..), Functor (..), Int, Maybe (..),
Monad (..), Monoid (..), Num (..), all, const, id, ($), (.), (<$>))
import Control.Applicative (Applicative (..))
import Control.Lens ((<&>))
import Data.Distributive (Distributive (..))
import Data.Fin (Fin)
import Data.Functor.Apply (Apply (..))
import Data.Functor.Rep (Representable (..))
import Data.Nat
import Data.Proxy (Proxy (..))
import Data.Semigroup (Semigroup (..))
import Data.Typeable (Typeable)
import qualified Control.Lens as I
import qualified Data.Foldable as I (Foldable (..))
import qualified Data.Functor.Bind as I (Bind (..))
import qualified Data.Semigroup.Foldable as I (Foldable1 (..))
import qualified Data.Fin as F
import qualified Data.Type.Nat as N
newtype Vec n a = Vec { unVec :: Fin n -> a }
deriving (Typeable)
instance (Eq a, N.SNatI n) => Eq (Vec n a) where
Vec v == Vec u = all (\i -> u i == v i) F.universe
instance Functor (Vec n) where
fmap f (Vec v) = Vec (f . v)
instance N.SNatI n => I.Foldable (Vec n) where
foldMap = foldMap
instance Applicative (Vec n) where
pure = Vec . pure
(<*>) = zipWith ($)
_ *> x = x
x <* _ = x
#if MIN_VERSION_base(4,10,0)
liftA2 = zipWith
#endif
instance Monad (Vec n) where
return = pure
(>>=) = bind
_ >> x = x
instance Distributive (Vec n) where
distribute = Vec . distribute . fmap unVec
instance Representable (Vec n) where
type Rep (Vec n) = Fin n
tabulate = Vec
index = unVec
instance Semigroup a => Semigroup (Vec n a) where
Vec a <> Vec b = Vec (a <> b)
instance Monoid a => Monoid (Vec n a) where
mempty = Vec mempty
Vec a `mappend` Vec b = Vec (mappend a b)
instance Apply (Vec n) where
(<.>) = zipWith ($)
_ .> x = x
x <. _ = x
instance I.Bind (Vec n) where
(>>-) = bind
join = join
instance I.FunctorWithIndex (Fin n) (Vec n) where
imap = imap
instance N.SNatI n => I.FoldableWithIndex (Fin n) (Vec n) where
ifoldMap = ifoldMap
ifoldr = ifoldr
empty :: Vec 'Z a
empty = Vec F.absurd
singleton :: a -> Vec ('S 'Z) a
singleton = Vec . const
toList :: N.SNatI n => Vec n a -> [a]
toList v = unVec v <$> F.universe
fromList :: N.SNatI n => [a] -> Maybe (Vec n a)
fromList = getFromList (N.induction1 start step) where
start :: FromList 'Z a
start = FromList $ \xs -> case xs of
[] -> Just empty
(_ : _) -> Nothing
step :: FromList n a -> FromList ('N.S n) a
step (FromList f) = FromList $ \xs -> case xs of
[] -> Nothing
(x : xs') -> cons x <$> f xs'
newtype FromList n a = FromList { getFromList :: [a] -> Maybe (Vec n a) }
_Vec :: N.SNatI n => I.Prism' [a] (Vec n a)
_Vec = I.prism' toList fromList
fromListPrefix :: N.SNatI n => [a] -> Maybe (Vec n a)
fromListPrefix = getFromList (N.induction1 start step) where
start :: FromList 'Z a
start = FromList $ \_ -> Just empty
step :: FromList n a -> FromList ('N.S n) a
step (FromList f) = FromList $ \xs -> case xs of
[] -> Nothing
(x : xs') -> cons x <$> f xs'
reifyList :: [a] -> (forall n. N.InlineInduction n => Vec n a -> r) -> r
reifyList [] f = f empty
reifyList (x : xs) f = reifyList xs $ \xs' -> f (cons x xs')
(!) :: Vec n a -> Fin n -> a
(!) = unVec
ix :: Fin n -> I.Lens' (Vec n a) a
ix i f (Vec v) = f (v i) <&> \a -> Vec $ \j ->
if i == j
then a
else v j
_Cons :: I.Iso (Vec ('S n) a) (Vec ('S n) b) (a, Vec n a) (b, Vec n b)
_Cons = I.iso (\(Vec v) -> (v F.Z, Vec (v . F.S))) (\(x, xs) -> cons x xs)
_head :: I.Lens' (Vec ('S n) a) a
_head f (Vec v) = f (v F.Z) <&> \a -> Vec $ \j -> case j of
F.Z -> a
_ -> v j
{-# INLINE head #-}
_tail :: I.Lens' (Vec ('S n) a) (Vec n a)
_tail f (Vec v) = f (Vec (v . F.S)) <&> \xs -> cons (v F.Z) xs
{-# INLINE _tail #-}
cons :: a -> Vec n a -> Vec ('S n) a
cons x (Vec v) = Vec $ \i -> case i of
F.Z -> x
F.S j -> v j
head :: Vec ('S n) a -> a
head (Vec v) = v F.Z
tail :: Vec ('S n) a -> Vec n a
tail (Vec v) = Vec (v . F.S)
map :: (a -> b) -> Vec n a -> Vec n b
map f (Vec v) = Vec (f . v)
imap :: (Fin n -> a -> b) -> Vec n a -> Vec n b
imap f (Vec v) = Vec $ \i -> f i (v i)
foldMap :: (Monoid m, N.SNatI n) => (a -> m) -> Vec n a -> m
foldMap f (Vec v) = I.foldMap (f . v) F.universe
foldMap1 :: (Semigroup s, N.SNatI n) => (a -> s) -> Vec ('S n) a -> s
foldMap1 f (Vec v) = I.foldMap1 (f . v) F.universe1
ifoldMap :: (Monoid m, N.SNatI n) => (Fin n -> a -> m) -> Vec n a -> m
ifoldMap f (Vec v) = I.foldMap (\i -> f i (v i)) F.universe
ifoldMap1 :: (Semigroup s, N.SNatI n) => (Fin ('S n) -> a -> s) -> Vec ('S n) a -> s
ifoldMap1 f (Vec v) = I.foldMap1 (\i -> f i (v i)) F.universe1
foldr :: N.SNatI n => (a -> b -> b) -> b -> Vec n a -> b
foldr f z (Vec v) = I.foldr (\a b -> f (v a) b) z F.universe
ifoldr :: N.SNatI n => (Fin n -> a -> b -> b) -> b -> Vec n a -> b
ifoldr f z (Vec v) = I.foldr (\a b -> f a (v a) b) z F.universe
foldl' :: N.SNatI n => (b -> a -> b) -> b -> Vec n a -> b
foldl' f z (Vec v) = I.foldl' (\b a -> f b (v a)) z F.universe
length :: forall n a. N.SNatI n => Vec n a -> Int
length _ = N.reflectToNum (Proxy :: Proxy n)
null :: forall n a. N.SNatI n => Vec n a -> Bool
null _ = case N.snat :: N.SNat n of
N.SZ -> True
N.SS -> False
sum :: (Num a, N.SNatI n) => Vec n a -> a
sum (Vec v) = I.foldl' (\x i -> x + v i) 0 F.universe
product :: (Num a, N.SNatI n) => Vec n a -> a
product (Vec v) = I.foldl' (\x i -> x * v i) 1 F.universe
zipWith :: (a -> b -> c) -> Vec n a -> Vec n b -> Vec n c
zipWith f (Vec xs) (Vec ys) = Vec $ \i -> f (xs i) (ys i)
izipWith :: (Fin n -> a -> b -> c) -> Vec n a -> Vec n b -> Vec n c
izipWith f (Vec xs) (Vec ys) = Vec $ \i -> f i (xs i) (ys i)
bind :: Vec n a -> (a -> Vec n b) -> Vec n b
bind m k = Vec $ unVec m >>= unVec . k
join :: Vec n (Vec n a) -> Vec n a
join (Vec v) = Vec $ \i -> unVec (v i) i
universe :: N.SNatI n => Vec n (Fin n)
universe = Vec id