{-# LANGUAGE CPP #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE UndecidableInstances #-}
module Data.Vec.Pull (
Vec (..),
empty,
singleton,
toList,
fromList,
fromListPrefix,
reifyList,
(!),
tabulate,
cons,
snoc,
head,
tail,
reverse,
foldMap,
foldMap1,
ifoldMap,
ifoldMap1,
foldr,
ifoldr,
foldl',
length,
null,
sum,
product,
map,
imap,
zipWith,
izipWith,
repeat,
bind,
join,
universe,
) where
import Prelude
(Bool (..), Eq (..), Functor (..), Int, Maybe (..), Monad (..),
Num (..), all, const, id, ($), (.))
import Control.Applicative (Applicative (..), (<$>))
import Data.Fin (Fin (..))
import Data.List.NonEmpty (NonEmpty (..))
import Data.Monoid (Monoid (..))
import Data.Nat (Nat (..))
import Data.Proxy (Proxy (..))
import Data.Semigroup (Semigroup (..))
import Data.Typeable (Typeable)
import qualified Data.Foldable as I (Foldable (..))
#ifdef MIN_VERSION_adjunctions
import qualified Data.Functor.Rep as I (Representable (..))
#endif
#ifdef MIN_VERSION_distributive
import Data.Distributive (Distributive (..))
#endif
#ifdef MIN_VERSION_semigroupoids
import Data.Functor.Apply (Apply (..))
import qualified Data.Functor.Bind as I (Bind (..))
import qualified Data.Semigroup.Foldable as I (Foldable1 (..))
#endif
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
#ifdef MIN_VERSION_semigroupoids
instance (N.SNatI m, n ~ 'S m) => I.Foldable1 (Vec n) where
foldMap1 = foldMap1
#endif
instance Applicative (Vec n) where
pure = repeat
(<*>) = 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
#ifdef MIN_VERSION_distributive
instance Distributive (Vec n) where
distribute = Vec . distribute . fmap unVec
#ifdef MIN_VERSION_adjunctions
instance I.Representable (Vec n) where
type Rep (Vec n) = Fin n
tabulate = Vec
index = unVec
#endif
#endif
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)
#ifdef MIN_VERSION_semigroupoids
instance Apply (Vec n) where
(<.>) = zipWith ($)
_ .> x = x
x <. _ = x
liftF2 = zipWith
instance I.Bind (Vec n) where
(>>-) = bind
join = join
#endif
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) }
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
tabulate :: (Fin n -> a) -> Vec n a
tabulate = Vec
cons :: a -> Vec n a -> Vec ('S n) a
cons x (Vec v) = Vec $ \i -> case i of
FZ -> x
FS j -> v j
snoc :: forall a n. N.InlineInduction n => Vec n a -> a -> Vec ('S n) a
snoc (Vec xs) x = Vec $ \i -> case F.isMax i of
Nothing -> x
Just i' -> xs i'
head :: Vec ('S n) a -> a
head (Vec v) = v FZ
tail :: Vec ('S n) a -> Vec n a
tail (Vec v) = Vec (v . FS)
reverse :: forall n a. N.InlineInduction n => Vec n a -> Vec n a
reverse (Vec v) = Vec (v . F.mirror)
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
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
foldMap1 :: (Semigroup s, N.SNatI n) => (a -> s) -> Vec ('S n) a -> s
foldMap1 f (Vec v) = neFoldMap (f . v) F.universe1
ifoldMap1 :: (Semigroup s, N.SNatI n) => (Fin ('S n) -> a -> s) -> Vec ('S n) a -> s
ifoldMap1 f (Vec v) = neFoldMap (\i -> f i (v i)) F.universe1
neFoldMap :: Semigroup s => (a -> s) -> NonEmpty a -> s
neFoldMap f (z :| zs) = go z zs where
go x [] = f x
go x (y : ys) = f x <> go y ys
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)
repeat :: x -> Vec n x
repeat = Vec . pure
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