module Camfort.Helpers.Vec
(
EqT(..)
, ExistsEqT(..)
, Nat(..)
, Natural(..)
, Vec(..)
, VecBox(..)
, VecList(..)
, (!!)
, findIndex
, fromList
, fromLists
, length
, lengthN
, proveEqSize
, proveNonEmpty
, replace
, toList
, zip
, zipWith
) where
import Prelude hiding (length, zip, zipWith, take, drop, (!!))
import Data.Proxy
import Unsafe.Coerce
data Nat = Z | S Nat
data Natural (n :: Nat) where
Zero :: Natural Z
Succ :: Natural n -> Natural (S n)
deriving instance Show (Natural n)
data NatBox where NatBox :: Natural n -> NatBox
deriving instance Show NatBox
class IsNatural (n :: Nat) where
fromNat :: Proxy n -> Int
instance IsNatural Z where
fromNat Proxy = 0
instance IsNatural n => IsNatural (S n) where
fromNat Proxy = 1 + fromNat (Proxy :: Proxy n)
data Vec (n :: Nat) a where
Nil :: Vec Z a
Cons :: a -> Vec n a -> Vec (S n) a
length :: Vec n a -> Int
length Nil = 0
length (Cons _ xs) = 1 + length xs
lengthN :: Vec n a -> Natural n
lengthN Nil = Zero
lengthN (Cons _ xs) = Succ $ lengthN xs
instance Functor (Vec n) where
fmap _ Nil = Nil
fmap f (Cons x xs) = Cons (f x) (fmap f xs)
deriving instance Eq a => Eq (Vec n a)
instance Ord a => Ord (Vec n a) where
Nil <= _ = True
(Cons x xs) <= (Cons y ys) | xs == ys = x <= y
| otherwise = xs <= ys
instance Show a => Show (Vec n a) where
show xs = "<" ++ showV xs ++ ">"
where
showV :: forall n a . Show a => Vec n a -> String
showV Nil = ""
showV (Cons x Nil) = show x
showV (Cons x xs) = show x ++ "," ++ showV xs
instance Foldable (Vec n) where
foldr _ acc Nil = acc
foldr f acc (Cons x xs) = foldr f (f x acc) xs
zipWith :: (a -> b -> c) -> Vec n a -> Vec n b -> Vec n c
zipWith _ Nil Nil = Nil
zipWith f (Cons x xs) (Cons y ys) = Cons (f x y) (zipWith f xs ys)
zip :: Vec n a -> Vec n b -> Vec n (a,b)
zip = zipWith (,)
findIndex :: (a -> Bool) -> Vec n a -> Maybe Int
findIndex = go 0
where
go :: Int -> (a -> Bool) -> Vec n a -> Maybe Int
go _ _ Nil = Nothing
go acc p (Cons x xs)
| p x = Just acc
| otherwise = go (acc + 1) p xs
(!!) :: Vec n a -> Int -> a
Cons x _ !! 0 = x
Cons _ v' !! n = v' !! (n 1)
replace :: Int -> a -> Vec n a -> Vec n a
replace 0 a (Cons _ xs) = Cons a xs
replace n a (Cons x xs) = Cons x (replace (n1) a xs)
replace _ _ Nil = error "Found asymmetry is beyond the limits."
data EqT a b where
ReflEq :: EqT a a
data ExistsEqT t n where
ExistsEqT :: EqT (t m) n -> ExistsEqT t n
data VecBox a where
VecBox :: Vec n a -> VecBox a
fromList :: [a] -> VecBox a
fromList = foldr (\x (VecBox xs) -> VecBox (Cons x xs)) (VecBox Nil)
toList :: Vec n a -> [ a ]
toList Nil = [ ]
toList (Cons x xs) = x : toList xs
proveEqSize :: Vec n a -> Vec m b -> Maybe (EqT m n)
proveEqSize Nil Nil = return ReflEq
proveEqSize (Cons _ xs) (Cons _ ys) = do
ReflEq <- proveEqSize xs ys
return ReflEq
proveEqSize _ _ = Nothing
proveNonEmpty :: Vec n a -> Maybe (ExistsEqT S n)
proveNonEmpty v =
case v of
Nil -> Nothing
(Cons _ _) -> Just $ ExistsEqT ReflEq
data VecList a where VL :: [Vec n a] -> VecList a
fromLists :: forall a . [[a]] -> VecList a
fromLists [] = VL ([] :: [Vec Z a])
fromLists (xs:xss) = consList (fromList xs) (fromLists xss)
where
consList :: VecBox a -> VecList a -> VecList a
consList (VecBox vec) (VL []) = VL [vec]
consList (VecBox vec) (VL xs) =
case preCondition vec xs of
ReflEq -> VL (vec : xs)
where
preCondition :: forall n n1 a . Vec n a -> [Vec n1 a] -> EqT n n1
preCondition _ _ = unsafeCoerce ReflEq