Removed 'group' - Div type family is not instanced for Decimals
[matthijs/master-project/support/tfvec.git] / Data / Param / TFVec.hs
1 ------------------------------------------------------------------------------
2 -- |
3 -- Module       : Data.Param.TFVec
4 -- Copyright    : (c) 2009 Christiaan Baaij
5 -- Licence      : BSD-style (see the file LICENCE)
6 --
7 -- Maintainer   : christiaan.baaij@gmail.com
8 -- Stability    : experimental
9 -- Portability  : non-portable
10 --
11 -- 'TFVec': Fixed sized vectors. Vectors with numerically parameterized size,
12 --          using type-level numerals from 'tfp' library
13 --
14 ------------------------------------------------------------------------------
15
16 module Data.Param.TFVec
17   ( TFVec
18   , empty
19   , (+>)
20   , singleton
21   , vectorCPS
22   , vectorTH
23   , unsafeVector
24   , readTFVec
25   , length
26   , lengthT
27   , fromVector
28   , null
29   , (!)
30   , replace
31   , head
32   , last
33   , init
34   , tail
35   , take
36   , drop
37   , select
38 --  , group
39   , (<+)
40   , (++)
41   , map
42   , zipWith
43   , foldl
44   , foldr
45   , zip
46   , unzip
47   , shiftl
48   , shiftr
49   , rotl
50   , rotr
51   , concat
52   , reverse
53   , iterate
54   , generate
55   , copy
56   ) where
57     
58
59 import Types
60 import Types.Data.Num.Decimal.Literals.TH
61 import Data.RangedWord
62
63 import Data.Generics (Data, Typeable)
64 import qualified Prelude as P
65 import Prelude hiding (
66   null, length, head, tail, last, init, take, drop, (++), map, foldl, foldr,
67   zipWith, zip, unzip, concat, reverse, iterate )
68 import qualified Data.Foldable as DF (Foldable, foldr)
69 import qualified Data.Traversable as DT (Traversable(traverse))
70 import Language.Haskell.TH
71 import Language.Haskell.TH.Syntax (Lift(..))
72
73 newtype (NaturalT s) => TFVec s a = TFVec {unTFVec :: [a]}
74   deriving (Eq, Typeable)
75
76 deriving instance (NaturalT s, Typeable s, Data s, Typeable a, Data a) => Data (TFVec s a)
77
78 -- ==========================
79 -- = Constructing functions =
80 -- ==========================
81                                                   
82 empty :: TFVec D0 a
83 empty = TFVec []
84
85 (+>) :: a -> TFVec s a -> TFVec (Succ s) a
86 x +> (TFVec xs) = TFVec (x:xs)
87
88 infix 5 +>
89
90 singleton :: a -> TFVec D1 a
91 singleton x = x +> empty
92
93 vectorCPS :: [a] -> (forall s . NaturalT s => TFVec s a -> w) -> w
94 vectorCPS xs = unsafeVectorCPS (toInteger (P.length xs)) xs
95
96 vectorTH :: Lift a => [a] -> ExpQ
97 vectorTH xs = (vectorCPS xs) lift
98
99 unsafeVector :: NaturalT s => s -> [a] -> TFVec s a
100 unsafeVector l xs
101   | fromIntegerT l /= P.length xs =
102     error (show 'unsafeVector P.++ ": dynamic/static lenght mismatch")
103   | otherwise = TFVec xs
104
105 readTFVec :: (Read a, NaturalT s) => String -> TFVec s a
106 readTFVec = read
107
108 readTFVecCPS :: Read a => String -> (forall s . NaturalT s => TFVec s a -> w) -> w
109 readTFVecCPS str = unsafeVectorCPS (toInteger l) xs
110  where fName = show 'readTFVecCPS
111        (xs,l) = case [(xs,l) | (xs,l,rest) <- readTFVecList str,  
112                            ("","") <- lexTFVec rest] of
113                        [(xs,l)] -> (xs,l)
114                        []   -> error (fName P.++ ": no parse")
115                        _    -> error (fName P.++ ": ambiguous parse")
116         
117 -- =======================
118 -- = Observing functions =
119 -- =======================
120 length :: forall s a . NaturalT s => TFVec s a -> Int
121 length _ = fromIntegerT (undefined :: s)
122
123 lengthT :: NaturalT s => TFVec s a -> s
124 lengthT = undefined
125
126 fromVector :: NaturalT s => TFVec s a -> [a]
127 fromVector (TFVec xs) = xs
128
129 null :: TFVec D0 a -> Bool
130 null _ = True
131
132 (!) ::  ( PositiveT s
133         , NaturalT u
134         , (s :>: u) ~ True) => TFVec s a -> RangedWord u -> a
135 (TFVec xs) ! i = xs !! (fromInteger (toInteger i))
136
137 -- ==========================
138 -- = Transforming functions =
139 -- ==========================
140 replace :: (PositiveT s, NaturalT u, (s :>: u) ~ True) =>
141   TFVec s a -> RangedWord u -> a -> TFVec s a
142 replace (TFVec xs) i y = TFVec $ replace' xs (toInteger i) y
143   where replace' []     _ _ = []
144         replace' (_:xs) 0 y = (y:xs)
145         replace' (x:xs) n y = x : (replace' xs (n-1) y)
146   
147 head :: PositiveT s => TFVec s a -> a
148 head = P.head . unTFVec
149
150 tail :: PositiveT s => TFVec s a -> TFVec (Pred s) a
151 tail = liftV P.tail
152
153 last :: PositiveT s => TFVec s a -> a
154 last = P.last . unTFVec
155
156 init :: PositiveT s => TFVec s a -> TFVec (Pred s) a
157 init = liftV P.init
158
159 take :: NaturalT i => i -> TFVec s a -> TFVec (Min s i) a
160 take i = liftV $ P.take (fromIntegerT i)
161
162 drop :: NaturalT i => i -> TFVec s a -> TFVec (s :-: (Min s i)) a
163 drop i = liftV $ P.drop (fromIntegerT i)
164
165 select :: (NaturalT f, NaturalT s, NaturalT n, (f :<: i) ~ True, 
166           (((s :*: n) :+: f) :<=: i) ~ True) => 
167           f -> s -> n -> TFVec i a -> TFVec n a
168 select f s n = liftV (select' f' s' n')
169   where (f', s', n') = (fromIntegerT f, fromIntegerT s, fromIntegerT n)
170         select' f s n = ((selectFirst0 s n).(P.drop f))
171         selectFirst0 :: Int -> Int -> [a] -> [a]
172         selectFirst0 s n l@(x:_)
173           | n > 0 = x : selectFirst0 s (n-1) (P.drop s l)
174           | otherwise = []
175         selectFirst0 _ 0 [] = []
176
177 -- group :: PositiveT n => n -> TFVec s a -> TFVec (Div s n) (TFVec n a)
178 -- group n = liftV (group' (fromIntegerT n))
179 --   where group' :: Int -> [a] -> [TFVec s a]
180 --         group' n xs = case splitAtM n xs of
181 --                         Nothing -> []
182 --                         Just (ls, rs) -> TFVec ls : group' n rs
183
184 (<+) :: TFVec s a -> a -> TFVec (Succ s) a
185 (<+) (TFVec xs) x = TFVec (xs P.++ [x])
186
187 (++) :: TFVec s a -> TFVec s2 a -> TFVec (s :+: s2) a
188 (++) = liftV2 (P.++)
189
190 infixl 5 <+
191 infixr 5 ++
192
193 map :: (a -> b) -> TFVec s a -> TFVec s b
194 map f = liftV (P.map f)
195
196 zipWith :: (a -> b -> c) -> TFVec s a -> TFVec s b -> TFVec s c
197 zipWith f = liftV2 (P.zipWith f)
198
199 foldl :: (a -> b -> a) -> a -> TFVec s b -> a
200 foldl f e = (P.foldl f e) . unTFVec
201
202 foldr :: (b -> a -> a) -> a -> TFVec s b -> a
203 foldr f e = (P.foldr f e) . unTFVec
204
205 zip :: TFVec s a -> TFVec s b -> TFVec s (a, b)
206 zip = liftV2 P.zip
207
208 unzip :: TFVec s (a, b) -> (TFVec s a, TFVec s b)
209 unzip (TFVec xs) = let (a,b) = P.unzip xs in (TFVec a, TFVec b)
210
211 shiftl :: (PositiveT s, NaturalT n, n ~ Pred s, s ~ Succ n) => 
212           TFVec s a -> a -> TFVec s a
213 shiftl xs x = x +> init xs
214
215 shiftr :: (PositiveT s, NaturalT n, n ~ Pred s, s ~ Succ n) => 
216           TFVec s a -> a -> TFVec s a
217 shiftr xs x = tail xs <+ x
218   
219 rotl :: (PositiveT s, s ~ Succ (Pred s)) => TFVec s a -> TFVec s a
220 rotl xs = last xs +> init xs
221
222 rotr :: (PositiveT s, s ~ Succ (Pred s)) => TFVec s a -> TFVec s a
223 rotr xs = tail xs <+ head xs
224
225 concat :: TFVec s1 (TFVec s2 a) -> TFVec (s1 :*: s2) a
226 concat = liftV (P.foldr ((P.++).unTFVec) [])
227
228 reverse :: TFVec s a -> TFVec s a
229 reverse = liftV P.reverse
230
231 iterate :: NaturalT s => s -> (a -> a) -> a -> TFVec s a
232 iterate s f x = let s' = fromIntegerT s in TFVec (P.take s' $ P.iterate f x)
233
234 generate :: NaturalT s => s -> (a -> a) -> a -> TFVec s a
235 generate s f x = let s' = fromIntegerT s in TFVec (P.take s' $ P.tail $ P.iterate f x)
236
237 copy :: NaturalT s => s -> a -> TFVec s a
238 copy s x = iterate s id x
239
240 -- =============
241 -- = Instances =
242 -- =============
243 instance Show a => Show (TFVec s a) where
244   showsPrec _ = showV.unTFVec
245     where showV []      = showString "<>"
246           showV (x:xs)  = showChar '<' . shows x . showl xs
247                             where showl []      = showChar '>'
248                                   showl (x:xs)  = showChar ',' . shows x .
249                                                   showl xs
250
251 instance (Read a, NaturalT nT) => Read (TFVec nT a) where
252   readsPrec _ str
253     | all fitsLength possibilities = P.map toReadS possibilities
254     | otherwise = error (fName P.++ ": string/dynamic length mismatch")
255     where 
256       fName = "Data.Param.TFVec.read"
257       expectedL = fromIntegerT (undefined :: nT)
258       possibilities = readTFVecList str
259       fitsLength (_, l, _) = l == expectedL
260       toReadS (xs, _, rest) = (TFVec xs, rest)
261       
262 instance NaturalT s => DF.Foldable (TFVec s) where
263  foldr = foldr
264  
265 instance NaturalT s => Functor (TFVec s) where
266  fmap = map
267
268 instance NaturalT s => DT.Traversable (TFVec s) where 
269   traverse f = (fmap TFVec).(DT.traverse f).unTFVec
270
271 instance (Lift a, NaturalT nT) => Lift (TFVec nT a) where
272   lift (TFVec xs) = [|  unsafeTFVecCoerse 
273                         $(decLiteralV (fromIntegerT (undefined :: nT))) 
274                         (TFVec xs) |]
275
276 -- ======================
277 -- = Internal Functions =
278 -- ======================
279 liftV :: ([a] -> [b]) -> TFVec nT a -> TFVec nT' b
280 liftV f = TFVec . f . unTFVec
281
282 liftV2 :: ([a] -> [b] -> [c]) -> TFVec s a -> TFVec s2 b -> TFVec s3 c
283 liftV2 f a b = TFVec (f (unTFVec a) (unTFVec b))
284
285 splitAtM :: Int -> [a] -> Maybe ([a],[a])
286 splitAtM n xs = splitAtM' n [] xs
287   where splitAtM' 0 xs ys = Just (xs, ys)
288         splitAtM' n xs (y:ys) | n > 0 = do
289           (ls, rs) <- splitAtM' (n-1) xs ys
290           return (y:ls,rs)
291         splitAtM' _ _ _ = Nothing
292
293 unsafeTFVecCoerse :: nT' -> TFVec nT a -> TFVec nT' a
294 unsafeTFVecCoerse _ (TFVec v) = (TFVec v)
295
296 unsafeVectorCPS :: forall a w . Integer -> [a] ->
297                         (forall s . NaturalT s => TFVec s a -> w) -> w
298 unsafeVectorCPS l xs f = reifyNaturalD l 
299                         (\(_ :: lt) -> f ((TFVec xs) :: (TFVec lt a)))
300
301 readTFVecList :: Read a => String -> [([a], Int, String)]
302 readTFVecList = readParen' False (\r -> [pr | ("<",s) <- lexTFVec r,
303                                               pr <- readl s])
304   where
305     readl   s = [([],0,t) | (">",t) <- lexTFVec s] P.++
306                             [(x:xs,1+n,u) | (x,t)       <- reads s,
307                                             (xs, n, u)  <- readl' t]
308     readl'  s = [([],0,t) | (">",t) <- lexTFVec s] P.++
309                             [(x:xs,1+n,v) | (",",t)   <- lex s,
310                                             (x,u)     <- reads t,
311                                             (xs,n,v)  <- readl' u]
312     readParen' b g  = if b then mandatory else optional
313       where optional r  = g r P.++ mandatory r
314             mandatory r = [(x,n,u) | ("(",s)  <- lexTFVec r,
315                                       (x,n,t) <- optional s,
316                                       (")",u) <- lexTFVec t]
317
318 -- Custom lexer for FSVecs, we cannot use lex directly because it considers
319 -- sequences of < and > as unique lexemes, and that breaks nested FSVecs, e.g.
320 -- <<1,2><3,4>>
321 lexTFVec :: ReadS String
322 lexTFVec ('>':rest) = [(">",rest)]
323 lexTFVec ('<':rest) = [("<",rest)]
324 lexTFVec str = lex str
325