0 | module Data.CheckedEmpty.List
  1 |
  2 | import Data.Bool
  3 | import Data.List1
  4 | import Data.Vect
  5 | import Data.Zippable
  6 |
  7 | import public Language.Implicits.IfUnsolved
  8 |
  9 | %default total
 10 |
 11 | --- Types definitions ---
 12 |
 13 | public export
 14 | data Lst : (definitelyNotEmpty : Bool) -> Type -> Type where
 15 |   Nil  : Lst False a
 16 |   (::) : (0 _ : True `IfUnsolved` ine) => (0 _ : True `IfUnsolved` ne) =>
 17 |          a -> Lst ine a -> Lst ne a
 18 |
 19 | %name Lst xs, ys, zs
 20 |
 21 | ||| An alias for a list that definitely may be empty.
 22 | ||| Don't use this if you can be polymorphic on the boolean type argument.
 23 | public export %inline
 24 | Lst0 : Type -> Type
 25 | Lst0 = Lst False
 26 |
 27 | public export %inline
 28 | Lst1 : Type -> Type
 29 | Lst1 = Lst True
 30 |
 31 | --- Basic functions ---
 32 |
 33 | public export
 34 | length : Lst ne a -> Nat
 35 | length []      = Z
 36 | length (_::xs) = S $ length xs
 37 |
 38 | public export %inline
 39 | (.length) : Lst ne a -> Nat
 40 | xs.length = length xs
 41 |
 42 | public export
 43 | (++) : Lst nel a -> Lst ner a -> Lst (nel || ner) a
 44 | []      ++ ys = ys
 45 | (x::xs) ++ ys = x :: xs ++ ys
 46 |
 47 | public export
 48 | Semigroup (Lst ne a) where
 49 |   xs <+> ys = rewrite sym $ orSameNeutral ne in xs ++ ys
 50 |
 51 | public export
 52 | Monoid (Lst0 a) where
 53 |   neutral = []
 54 |
 55 | public export
 56 | index' : (xs : Lst ne a) -> Fin xs.length -> a
 57 | index' (x::_ ) FZ     = x
 58 | index' (_::xs) (FS i) = index' xs i
 59 |
 60 | public export %inline
 61 | index : Fin n -> (xs : Lst ne a) -> (0 _ : n = xs.length) => a
 62 | index i xs @{Refl} = index' xs i
 63 |
 64 | --- Creation ---
 65 |
 66 | public export
 67 | iterateN : (n : Nat) -> (a -> a) -> a -> Lst (n /= 0) a
 68 | iterateN Z     _ x = []
 69 | iterateN (S n) f x = x :: iterateN n f x
 70 |
 71 | public export
 72 | tabulateN : (n : Nat) -> (Fin n -> a) -> Lst (n /= 0) a
 73 | tabulateN 0     _ = []
 74 | tabulateN (S k) f = f FZ :: tabulateN k (f . FS)
 75 |
 76 | public export
 77 | replicate : (n : Nat) -> a -> Lst (n /= 0) a
 78 | replicate Z     _ = []
 79 | replicate (S k) x = x :: replicate k x
 80 |
 81 | covering
 82 | public export
 83 | iterate : (a -> Maybe a) -> a -> Lst0 a
 84 | iterate f x = x :: case f x of
 85 |   Nothing => []
 86 |   Just y  => iterate f y
 87 |
 88 | covering
 89 | public export
 90 | unfoldr : (b -> Maybe (a, b)) -> b -> Lst0 a
 91 | unfoldr f c = case f c of
 92 |   Nothing     => []
 93 |   Just (a, n) => a :: unfoldr f n
 94 |
 95 | --- Internal conversions ---
 96 |
 97 | -- Relaxation --
 98 |
 99 | public export
100 | relaxF : Lst ne a -> Lst0 a
101 | relaxF []      = []
102 | relaxF (x::xs) = x::xs
103 |
104 | public export %inline
105 | relaxT : Lst1 a -> Lst ne a
106 | relaxT (x::xs) = x::xs
107 |
108 | public export
109 | relaxAnd : Lst ne a -> Lst (ne && nx) a
110 | relaxAnd []      = []
111 | relaxAnd (x::xs) = x::xs
112 |
113 | %transform "relaxF=id"   relaxF   {ne} {a} = believe_me (\x => the (Lst ne a) x)
114 | %transform "relaxT=id"   relaxT   {ne} {a} = believe_me (\x => the (Lst ne a) x)
115 | %transform "relaxAnd=id" relaxAnd {ne} {a} = believe_me (\x => the (Lst ne a) x)
116 |
117 | -- Strengthening --
118 |
119 | public export
120 | strengthen : Lst ne a -> Maybe $ Lst1 a
121 | strengthen []      = Nothing
122 | strengthen (x::xs) = Just $ x::xs
123 |
124 | --- Functor ---
125 |
126 | public export
127 | Functor (Lst ne) where
128 |   map f []      = []
129 |   map f (x::xs) = f x :: map f xs
130 |
131 | namespace NEHeteroOps
132 |
133 |   public export
134 |   bind : Lst nel a -> (a -> Lst ner b) -> Lst (nel && ner) b
135 |   bind [] _ = []
136 |   bind wh@(x::xs) f = do
137 |     rewrite andCommutative nel ner
138 |     let Just nxs = strengthen xs
139 |       | Nothing => relaxAnd $ f x
140 |     rewrite sym $ orSameNeutral ner
141 |     relaxAnd $ f x ++ (assert_smaller wh nxs `bind` f)
142 |
143 |   public export %inline
144 |   bind' : Lst nel a -> Lst ner b -> Lst (nel && ner) b
145 |   bind' xs ys = xs `bind` \_ => ys
146 |
147 |   public export %inline
148 |   join' : Lst nel (Lst ner a) -> Lst (nel && ner) a
149 |   join' xs = xs `bind` id
150 |
151 |   public export %inline
152 |   ap : Lst nel (a -> b) -> Lst ner a -> Lst (nel && ner) b
153 |   ap xs ys = xs `bind` (<$> ys)
154 |
155 | public export %inline
156 | Applicative (Lst ne) where
157 |   pure x = [x]
158 |   xs <*> ys = rewrite sym $ andSameNeutral ne in xs `ap` ys
159 |
160 | public export %inline
161 | Alternative Lst0 where
162 |   empty = []
163 |   xs <|> ys = xs ++ ys
164 |
165 | public export %inline
166 | Monad (Lst ne) where
167 |   xs >>= f = rewrite sym $ andSameNeutral ne in xs `bind` f
168 |
169 | --- Folds ---
170 |
171 | public export
172 | foldrLazy : (op : a -> Lazy b -> b) -> (init : Lazy b) -> Lst ne a -> b
173 | foldrLazy _  init []      = init
174 | foldrLazy op init (x::xs) = x `op` foldrLazy op init xs
175 |
176 | public export
177 | Foldable (Lst ne) where
178 |   foldr c n []      = n
179 |   foldr c n (x::xs) = c x (foldr c n xs)
180 |
181 |   foldl f q []      = q
182 |   foldl f q (x::xs) = foldl f (f q x) xs
183 |
184 |   null []     = True
185 |   null (_::_) = False
186 |
187 |   toList []      = []
188 |   toList (x::xs) = x :: toList xs
189 |
190 |   foldMap f = foldl (\acc, elem => acc <+> f elem) neutral
191 |
192 | public export
193 | foldl1 : (a -> a -> a) -> Lst1 a -> a
194 | foldl1 f (x::xs) = foldl f x xs
195 |
196 | public export
197 | foldr1 : (op : a -> Lazy a -> a) -> Lst1 a -> a
198 | foldr1 op [x]               = x
199 | foldr1 op xyys@(x::(y::ys)) = op x $ foldr1 op $ assert_smaller xyys $ y::ys
200 |
201 | public export
202 | Traversable (Lst ne) where
203 |   traverse f []      = pure []
204 |   traverse f (x::xs) = [| f x :: traverse f xs |]
205 |
206 | --- Reversing ---
207 |
208 | public export
209 | reverse : Lst ne a -> Lst ne a
210 | reverse []      = []
211 | reverse (x::xs) = foldl (flip (::)) [x] xs
212 |
213 | --- Picking ---
214 |
215 | public export
216 | head : Lst1 a -> a
217 | head (x::_) = x
218 |
219 | public export
220 | head' : Lst ne a -> Maybe a
221 | head' = map head . strengthen
222 |
223 | public export
224 | tail : Lst1 a -> Lst0 a
225 | tail (_::xs) = relaxF xs
226 |
227 | public export
228 | tail' : Lst ne a -> Maybe $ Lst0 a
229 | tail' = map tail . strengthen
230 |
231 | public export
232 | last : Lst1 a -> a
233 | last [x]     = x
234 | last wh@(_::(y::ys)) = last $ assert_smaller wh $ y::ys
235 |
236 | public export
237 | last' : Lst ne a -> Maybe a
238 | last' = map last . strengthen
239 |
240 | public export
241 | init : Lst1 a -> Lst0 a
242 | init [x] = []
243 | init wh@(x::(y::ys)) = x :: init (assert_smaller wh $ y::ys)
244 |
245 | public export
246 | init' : Lst ne a -> Maybe $ Lst0 a
247 | init' = map init . strengthen
248 |
249 | public export
250 | unsnoc : Lst1 a -> (Lst0 a, a)
251 | unsnoc = go [] where
252 |   go : (rev : Lst0 a) -> Lst1 a -> (Lst0 a, a)
253 |   go rev xxs@(x::xs) = case strengthen xs of
254 |     Nothing  => (reverse rev, x)
255 |     Just xs' => go (x::rev) $ assert_smaller xxs xs'
256 |
257 | -- Returns the longest first
258 | public export
259 | tails : Lst ne a -> Lst1 $ Lst0 a
260 | tails []          = [ [] ]
261 | tails xxs@(x::xs) = relaxF xxs :: tails (assert_smaller xxs xs)
262 |
263 | -- Returns the longest first
264 | public export
265 | tails1 : Lst ne a -> Lst ne $ Lst1 a
266 | tails1 [] = []
267 | tails1 xxs@(x::xs) = (x::xs) :: case strengthen xs of
268 |   Nothing  => []
269 |   Just xs' => relaxF $ tails1 $ assert_smaller xxs xs'
270 |
271 | -- Returns the shortest first
272 | public export
273 | inits : Lst ne a -> Lst1 $ Lst0 a
274 | inits []      = [ [] ]
275 | inits (x::xs) = [] :: ((x::) <$> inits xs)
276 |
277 | -- Returns the shortest first
278 | public export
279 | inits1 : Lst ne a -> Lst ne $ Lst1 a
280 | inits1 []      = []
281 | inits1 (x::xs) = [x] :: ((x::) <$> inits1 xs)
282 |
283 | --- Sublisting ---
284 |
285 | public export
286 | take : (n : Nat) -> Lst ne a -> Lst (ne && n /= 0) a
287 | take Z     _       = rewrite andFalseFalse ne in []
288 | take _     []      = []
289 | take (S k) (x::xs) = x :: take k xs
290 |
291 | public export
292 | drop : (n : Nat) -> Lst ne a -> Lst0 a
293 | drop Z     xs      = relaxF xs
294 | drop (S _) []      = []
295 | drop (S n) (_::xs) = drop n $ relaxF xs
296 |
297 | public export
298 | takeWhile : (a -> Bool) -> Lst ne a -> Lst0 a
299 | takeWhile p []      = []
300 | takeWhile p (x::xs) = if p x then x :: takeWhile p xs else []
301 |
302 | public export
303 | dropWhile : (a -> Bool) -> Lst ne a -> Lst0 a
304 | dropWhile p []      = []
305 | dropWhile p (x::xs) = if p x then dropWhile p xs else x::xs
306 |
307 | --- Zippings ---
308 |
309 | public export
310 | Zippable (Lst ne) where
311 |   zipWith _ [] _ = []
312 |   zipWith _ _ [] = []
313 |   zipWith f xxs@((x::xs) @{_} @{ine}) (y::ys) =
314 |     (f x y :: zipWith f (assert_smaller xxs $ relaxF xs) (relaxF ys)) @{%search} @{ine}
315 |
316 |   zipWith3 _ [] _ _ = []
317 |   zipWith3 _ _ [] _ = []
318 |   zipWith3 _ _ _ [] = []
319 |   zipWith3 f xxs@((x::xs) @{_} @{ine}) (y::ys) (z::zs) =
320 |     (f x y z :: zipWith3 f (assert_smaller xxs $ relaxF xs) (relaxF ys) (relaxF zs)) @{%search} @{ine}
321 |
322 |   unzipWith f [] = ([], [])
323 |   unzipWith f (x::xs) = do
324 |     let (y, z) = f x
325 |     let (ys, zs) = unzipWith f xs
326 |     (y::ys, z::zs)
327 |
328 |   unzipWith3 f [] = ([], [], [])
329 |   unzipWith3 f (x::xs) = do
330 |     let (a, b, c) = f x
331 |     let (as, bs, cs) = unzipWith3 f xs
332 |     (a::as, b::bs, c::cs)
333 |
334 | public export
335 | zipWithStream : (a -> b -> c) -> Stream a -> Lst ne b -> Lst ne c
336 | zipWithStream _ _       []      = []
337 | zipWithStream f (x::xs) (y::ys) = f x y :: zipWithStream f xs ys
338 |
339 | public export %inline
340 | zipStream : Stream a -> Lst ne b -> Lst ne (a, b)
341 | zipStream = zipWithStream (,)
342 |
343 | --- Filtering ---
344 |
345 | public export
346 | filter : (a -> Bool) -> Lst ne a -> Lst0 a
347 | filter _ []      = []
348 | filter f (x::xs) = if f x then x :: filter f xs else filter f xs
349 |
350 | public export
351 | mapMaybe : (a -> Maybe b) -> Lst ne a -> Lst0 b
352 | mapMaybe _ [] = []
353 | mapMaybe f (x::xs) = case f x of
354 |                        Just y  => y :: mapMaybe f xs
355 |                        Nothing => mapMaybe f xs
356 |
357 | --- External conversions ---
358 |
359 | -- Foldable --
360 |
361 | public export
362 | fromFoldable : Foldable f => f a -> Lst0 a
363 | fromFoldable = foldr (::) []
364 |
365 | -- List --
366 |
367 | public export
368 | fromList : (xs : List a) -> Lst (not $ null xs) a
369 | fromList []      = []
370 | fromList (x::xs) = x :: fromList xs
371 |
372 | public export
373 | Cast (List a) (Lst0 a) where
374 |   cast xs = relaxF $ fromList xs
375 |
376 | -- List1 --
377 |
378 | public export
379 | fromList1 : List1 a -> Lst1 a
380 | fromList1 $ x:::xs = x :: fromList xs
381 |
382 | public export
383 | toList1 : Lst1 a -> List1 a
384 | toList1 $ x::xs = x ::: toList xs
385 |
386 | public export
387 | Cast (List1 a) (Lst True a) where
388 |   cast = fromList1
389 |
390 | public export
391 | Cast (Lst True a) (List1 a) where
392 |   cast = toList1
393 |
394 | -- Vect --
395 |
396 | public export
397 | fromVect : Vect n a -> Lst (n /= Z) a
398 | fromVect []      = []
399 | fromVect (x::xs) = x :: fromVect xs
400 |
401 | public export
402 | Cast (Vect n a) (Lst (n /= Z) a) where
403 |   cast = fromVect
404 |
405 | --- Range syntax ---
406 |
407 | public export %inline
408 | rangeFromTo : Range a => a -> a -> Lst0 a
409 | rangeFromTo l r = relaxF $ fromList $ rangeFromTo l r
410 |
411 | public export %inline
412 | rangeFromThenTo : Range a => a -> a -> a -> Lst0 a
413 | rangeFromThenTo x y z = relaxF $ fromList $ rangeFromThenTo x y z
414 |
415 | --- Showing ---
416 |
417 | export
418 | Show a => Show (Lst ne a) where
419 |   show = show . toList
420 |
421 | --- Properties ---
422 |
423 | -- type itself, inhabitance --
424 |
425 | export
426 | {0 xs : Lst _ _} -> {0 uns0 : _} -> {0 uns1 : _} ->
427 | Uninhabited ([] = (::) @{uns0} @{uns1} x xs) where
428 |   uninhabited Refl impossible
429 |
430 | export
431 | {0 xs : Lst _ _} -> {0 uns0 : _} -> {0 uns1 : _} ->
432 | Uninhabited ((::) @{uns0} @{uns1} x xs = []) where
433 |   uninhabited Refl impossible
434 |
435 | -- If either head or tail is not propositionally equal, conses are not propositionally equal
436 | export
437 | {0 xs : Lst _ _} ->
438 | {0 unsL0 : _} -> {0 unsL1 : _} ->
439 | {0 unsR0 : _} -> {0 unsR1 : _} ->
440 | Either (Uninhabited $ x === y) (Uninhabited $ xs === ys) =>
441 | Uninhabited ((::) @{unsL0} @{unsL1} x xs === (::) @{unsR0} @{unsR1} y ys) where
442 |   uninhabited @{Left  z} Refl = uninhabited @{z} Refl
443 |   uninhabited @{Right z} Refl = uninhabited @{z} Refl
444 |
445 | -- type itself, constructors --
446 |
447 | export
448 | Biinjective CheckedEmpty.List.(::) where
449 |   biinjective Refl = (Refl, Refl)
450 |
451 | -- map --
452 |
453 | export
454 | mapFusion : (g : b -> c) -> (f : a -> b) -> (xs : Lst ne a) -> map g (map f xs) = map (g . f) xs
455 | mapFusion g f []      = Refl
456 | mapFusion g f (x::xs) = rewrite mapFusion g f xs in Refl
457 |
458 | export
459 | mapExt : (xs : Lst ne _) -> ((x : _) -> f x = g x) -> map f xs = map g xs
460 | mapExt []      _  = Refl
461 | mapExt (x::xs) fg = rewrite fg x in cong (g x ::) $ mapExt _ fg
462 |