module Data.Param.FSVec
(FSVec, empty, (+>), singleton, vectorCPS, vectorTH,
#if __GLASGOW_HASKELL__ >= 609
v,
#endif
unsafeVector, reallyUnsafeVector, readFSVec, readFSVecCPS, length,
genericLength, lengthT, fromVector, null, (!), replace, head, last,
init, tail, take, drop, select, group, (<+), (++), map, zipWith,
foldl, foldr, zip, unzip, shiftl, shiftr, rotl, rotr, concat,
reverse, iterate, generate, copy
) where
import Data.TypeLevel.Num hiding ((),(+),(*),(>),(<),(>=),(<=),(==))
import Data.TypeLevel.Num.Aliases.TH (dec2TypeLevel)
import Data.Generics (Data, Typeable)
import qualified Prelude as P
import Prelude hiding (
null, length, head, tail, last, init, take, drop,
(++), map, foldl, foldr,
zipWith, zip, unzip,
concat, reverse, iterate)
import qualified Data.Foldable as DF (Foldable, foldr)
import qualified Data.Traversable as DT (Traversable(traverse))
import Language.Haskell.TH
import Language.Haskell.TH.Syntax (Lift(..))
#if __GLASGOW_HASKELL__ >= 609
import Language.Haskell.TH.Quote
#endif
newtype Nat s => FSVec s a = FSVec {unFSVec :: [a]}
deriving (Eq, Typeable, Data)
instance Show a => Show (FSVec s a) where
showsPrec _ = showV.unFSVec
where showV [] = showString "<>"
showV (x:xs) = showChar '<' . shows x . showl xs
where showl [] = showChar '>'
showl (x:xs) = showChar ',' . shows x .
showl xs
empty :: FSVec D0 a
empty = FSVec []
(+>) :: (Nat s, Pos s', Succ s s') => a -> FSVec s a -> FSVec s' a
x +> (FSVec xs) = FSVec (x:xs)
infixr 5 +>
singleton :: a -> FSVec D1 a
singleton x = x +> empty
vectorCPS :: [a] -> (forall s . Nat s => FSVec s a -> w) -> w
vectorCPS xs = unsafeVectorCPS (P.length xs) xs
vectorTH :: Lift a => [a] -> ExpQ
vectorTH xs = (vectorCPS xs) lift
#if __GLASGOW_HASKELL__ >= 609
v :: QuasiQuoter
v = QuasiQuoter parseFSVecExp parseFSVecPat
parseFSVecExp :: String -> ExpQ
parseFSVecExp str = undefined
parseFSVecPat :: String -> PatQ
parseFSVecPat = error "Data.Param.FSVec: quasiquoting paterns not supported"
#endif
unsafeVector :: Nat s => s -> [a] -> FSVec s a
unsafeVector l xs
| toNum l /= P.length xs =
error (show 'unsafeVector P.++ ": dynamic/static length mismatch")
| otherwise = FSVec xs
reallyUnsafeVector :: [a] -> FSVec s a
reallyUnsafeVector = FSVec
readFSVec :: (Read a, Nat s) => String -> FSVec s a
readFSVec = read
instance (Read a, Nat s) => Read (FSVec s a) where
readsPrec _ str
| all fitsLength posibilities = P.map toReadS posibilities
| otherwise = error (fName P.++ ": string/dynamic length mismatch")
where fName = "Data.Param.FSVec.read"
expectedL = toInt (undefined :: s)
posibilities = readFSVecList str
fitsLength (_, l, _) = l == expectedL
toReadS (xs, _, rest) = (FSVec xs, rest)
readFSVecCPS :: Read a => String -> (forall s . Nat s => FSVec s a -> w) -> w
readFSVecCPS str = unsafeVectorCPS l xs
where fName = show 'readFSVecCPS
(xs,l) = case [(xs,l) | (xs,l,rest) <- readFSVecList str,
("","") <- lexFSVec rest] of
[(xs,l)] -> (xs,l)
[] -> error (fName P.++ ": no parse")
_ -> error (fName P.++ ": ambiguous parse")
length :: forall s a . Nat s => FSVec s a -> Int
length _ = toInt (undefined :: s)
genericLength :: forall s a n . (Nat s, Num n) => FSVec s a -> n
genericLength _ = toNum (undefined :: s)
lengthT :: Nat s => FSVec s a -> s
lengthT = undefined
fromVector :: Nat s => FSVec s a -> [a]
fromVector (FSVec xs) = xs
null :: FSVec D0 a -> Bool
null _ = True
(!) :: (Pos s, Nat i, i :<: s) => FSVec s a -> i -> a
(FSVec xs) ! i = xs !! (toInt i)
replace :: (Nat s, Nat i) => FSVec s a -> i -> a -> FSVec s a
replace (FSVec xs) i y = FSVec $ replace' xs (toInt i) y
where replace' [] _ _ = []
replace' (_:xs) 0 y = (y:xs)
replace' (x:xs) n y = x : (replace' xs (n 1) y)
head :: Pos s => FSVec s a -> a
head = P.head . unFSVec
last :: Pos s => FSVec s a -> a
last = P.last . unFSVec
tail :: (Pos s, Succ s' s) => FSVec s a -> FSVec s' a
tail = liftV P.tail
init :: (Pos s, Succ s' s) => FSVec s a -> FSVec s' a
init = liftV P.init
take :: (Nat i, Nat s, Min s i s') => i -> FSVec s a -> FSVec s' a
take i = liftV $ P.take (toInt i)
drop :: (Nat i, Nat s, Min s i sm, Sub s sm s') => i -> FSVec s a -> FSVec s' a
drop i = liftV $ P.drop (toInt i)
select :: (Nat f, Nat s, Nat n, f :<: i,
Mul s n smn, Add f smn fasmn, fasmn :<=: i) =>
f -> s -> n -> FSVec i a -> FSVec n a
select f s n = liftV (select' f' s' n')
where (f', s', n') = (toInt f, toInt s, toInt n)
select' f s n = ((selectFirst0 s n).(P.drop f))
selectFirst0 :: Int -> Int -> [a] -> [a]
selectFirst0 s n l@(x:_)
| n > 0 = x : selectFirst0 s (n 1) (P.drop s l)
| otherwise = []
selectFirst0 _ 0 [] = []
group :: (Pos n, Nat s, Div s n s') =>
n -> FSVec s a -> FSVec s' (FSVec n a)
group n = liftV (group' (toInt n))
where group' :: Int -> [a] -> [FSVec s a]
group' n xs = case splitAtM n xs of
Nothing -> []
Just (ls, rs) -> FSVec ls : group' n rs
(<+) :: (Nat s, Pos s', Succ s s') => FSVec s a -> a -> FSVec s' a
(<+) (FSVec xs) x = FSVec (xs P.++ [x])
(++) :: (Nat s1, Nat s2, Add s1 s2 s3) =>
FSVec s1 a -> FSVec s2 a -> FSVec s3 a
(++) = liftV2 (P.++)
infixl 5 <+
infixr 5 ++
map :: Nat s => (a -> b) -> FSVec s a -> FSVec s b
map f = liftV (P.map f)
zipWith :: Nat s => (a -> b -> c) -> FSVec s a -> FSVec s b -> FSVec s c
zipWith f = liftV2 (P.zipWith f)
foldl :: Nat s => (a -> b -> a) -> a -> FSVec s b -> a
foldl f e = (P.foldl f e) . unFSVec
foldr :: Nat s => (b -> a -> a) -> a -> FSVec s b -> a
foldr f e = (P.foldr f e) . unFSVec
zip :: Nat s => FSVec s a -> FSVec s b -> FSVec s (a, b)
zip = liftV2 P.zip
unzip :: Nat s => FSVec s (a, b) -> (FSVec s a, FSVec s b)
unzip (FSVec xs) = let (a,b) = P.unzip xs in (FSVec a, FSVec b)
shiftl :: Pos s => FSVec s a -> a -> FSVec s a
shiftl xs x = liftV ((x:) . P.init) xs
shiftr :: Pos s => FSVec s a -> a -> FSVec s a
shiftr xs x = liftV (P.tail . (P.++[x])) xs
rotl :: forall s a . Nat s => FSVec s a -> FSVec s a
rotl = liftV rotl'
where vl = toInt (undefined :: s)
rotl' [] = []
rotl' xs = let (i,[l]) = splitAt (vl 1) xs
in l : i
rotr :: Nat s => FSVec s a -> FSVec s a
rotr = liftV rotr'
where rotr' [] = []
rotr' l@(x:_) = P.tail l P.++ [x]
concat :: (Nat s1, Nat s2, Nat s3, Mul s1 s2 s3) =>
FSVec s1 (FSVec s2 a) -> FSVec s3 a
concat = liftV (P.foldr ((P.++).unFSVec) [])
reverse :: Nat s => FSVec s a -> FSVec s a
reverse = liftV P.reverse
iterate :: Nat s => s -> (a -> a) -> a -> FSVec s a
iterate s f x = let s' = toInt s in FSVec (P.take s' $ P.iterate f x)
generate :: Nat s => s -> (a -> a) -> a -> FSVec s a
generate s f x = let s' = toInt s in FSVec (P.take s' $ P.tail $ P.iterate f x)
copy :: Nat s => s -> a -> FSVec s a
copy s x = iterate s id x
instance Nat s => DF.Foldable (FSVec s) where
foldr = foldr
instance Nat s => Functor (FSVec s) where
fmap = map
instance Nat s => DT.Traversable (FSVec s) where
traverse f = (fmap FSVec).(DT.traverse f).unFSVec
instance (Lift a, Nat s) => Lift (FSVec s a) where
lift (FSVec xs) = [| unsafeFSVecCoerce $(undefSigE lengthType) (FSVec xs) |]
where
lengthType :: TypeQ
lengthType = dec2TypeLevel $ toInt (undefined :: s)
liftV :: ([a] -> [b]) -> FSVec s a -> FSVec s' b
liftV f = FSVec . f . unFSVec
liftV2 :: ([a] -> [b] -> [c]) -> FSVec s1 a -> FSVec s2 b -> FSVec s3 c
liftV2 f a b = FSVec (f (unFSVec a) (unFSVec b))
splitAtM :: Int -> [a] -> Maybe ([a],[a])
splitAtM n xs = splitAtM' n [] xs
where splitAtM' 0 xs ys = Just (xs,ys)
splitAtM' n xs (y:ys) | n > 0 = do
(ls,rs) <- splitAtM' (n 1) xs ys
return (y:ls,rs)
splitAtM' _ _ _ = Nothing
unsafeFSVecCoerce :: s' -> FSVec s a -> FSVec s' a
unsafeFSVecCoerce _ (FSVec v) = (FSVec v)
undefSigE :: TypeQ -> ExpQ
undefSigE t = sigE [| undefined |] t
unsafeVectorCPS :: forall a w . Int -> [a] ->
(forall s . Nat s => FSVec s a -> w) -> w
unsafeVectorCPS l xs f = reifyIntegral l
(\(_ :: lt) -> f ((FSVec xs) :: (FSVec lt a)))
readFSVecList :: Read a => String -> [([a], Int, String)]
readFSVecList = readParen' False (\r -> [pr | ("<",s) <- lexFSVec r,
pr <- readl s])
where
readl s = [([],0,t) | (">",t) <- lexFSVec s] P.++
[(x:xs,1+n,u) | (x,t) <- reads s,
(xs,n,u) <- readl' t]
readl' s = [([],0,t) | (">",t) <- lexFSVec s] P.++
[(x:xs,1+n,v) | (",",t) <- lex s,
(x,u) <- reads t,
(xs,n,v) <- readl' u]
readParen' b g = if b then mandatory else optional
where optional r = g r P.++ mandatory r
mandatory r = [(x,n,u) | ("(",s) <- lexFSVec r,
(x,n,t) <- optional s,
(")",u) <- lexFSVec t ]
lexFSVec :: ReadS String
lexFSVec ('>':rest) = [(">",rest)]
lexFSVec ('<':rest) = [("<",rest)]
lexFSVec str = lex str