@@ -16,10 +16,10 @@ open import Data.Bool.Base as Bool
16
16
open import Data.Fin.Base using (Fin; zero; suc)
17
17
open import Data.Maybe.Base as Maybe using (Maybe; nothing; just; maybe′)
18
18
open import Data.Nat.Base as ℕ using (ℕ; zero; suc; _+_; _*_ ; _≤_ ; s≤s)
19
- open import Data.Product as Prod using (_×_; _,_)
19
+ open import Data.Product as Prod using (_×_; _,_; map₁; map₂′ )
20
20
open import Data.Sum.Base as Sum using (_⊎_; inj₁; inj₂)
21
21
open import Data.These.Base as These using (These; this; that; these)
22
- open import Function.Base using (id; _∘_ ; _∘′_; const; flip)
22
+ open import Function.Base using (id; _∘_ ; _∘′_; _∘₂_; const; flip)
23
23
open import Level using (Level)
24
24
open import Relation.Nullary using (does)
25
25
open import Relation.Nullary.Negation.Core using (¬?)
@@ -52,7 +52,7 @@ mapMaybe : (A → Maybe B) → List A → List B
52
52
mapMaybe p [] = []
53
53
mapMaybe p (x ∷ xs) with p x
54
54
... | just y = y ∷ mapMaybe p xs
55
- ... | nothing = mapMaybe p xs
55
+ ... | nothing = mapMaybe p xs
56
56
57
57
infixr 5 _++_
58
58
@@ -238,6 +238,51 @@ unfold P f {n = suc n} s with f s
238
238
... | nothing = []
239
239
... | just (x , s′) = x ∷ unfold P f s′
240
240
241
+ ------------------------------------------------------------------------
242
+ -- Operations for reversing lists
243
+
244
+ reverseAcc : List A → List A → List A
245
+ reverseAcc = foldl (flip _∷_)
246
+
247
+ reverse : List A → List A
248
+ reverse = reverseAcc []
249
+
250
+ -- "Reverse append" xs ʳ++ ys = reverse xs ++ ys
251
+
252
+ infixr 5 _ʳ++_
253
+
254
+ _ʳ++_ : List A → List A → List A
255
+ _ʳ++_ = flip reverseAcc
256
+
257
+ -- Snoc: Cons, but from the right.
258
+
259
+ infixl 6 _∷ʳ_
260
+
261
+ _∷ʳ_ : List A → A → List A
262
+ xs ∷ʳ x = xs ++ [ x ]
263
+
264
+
265
+
266
+ -- Backwards initialisation
267
+
268
+ infixl 5 _∷ʳ′_
269
+
270
+ data InitLast {A : Set a} : List A → Set a where
271
+ [] : InitLast []
272
+ _∷ʳ′_ : (xs : List A) (x : A) → InitLast (xs ∷ʳ x)
273
+
274
+ initLast : (xs : List A) → InitLast xs
275
+ initLast [] = []
276
+ initLast (x ∷ xs) with initLast xs
277
+ ... | [] = [] ∷ʳ′ x
278
+ ... | ys ∷ʳ′ y = (x ∷ ys) ∷ʳ′ y
279
+
280
+ -- uncons, but from the right
281
+ unsnoc : List A → Maybe (List A × A)
282
+ unsnoc as with initLast as
283
+ ... | [] = nothing
284
+ ... | xs ∷ʳ′ x = just (xs , x)
285
+
241
286
------------------------------------------------------------------------
242
287
-- Operations for deconstructing lists
243
288
@@ -273,55 +318,117 @@ drop zero xs = xs
273
318
drop (suc n) [] = []
274
319
drop (suc n) (x ∷ xs) = drop n xs
275
320
276
- splitAt : ℕ → List A → ( List A × List A)
321
+ splitAt : ℕ → List A → List A × List A
277
322
splitAt zero xs = ([] , xs)
278
323
splitAt (suc n) [] = ([] , [])
279
- splitAt (suc n) (x ∷ xs) with splitAt n xs
280
- ... | (ys , zs) = (x ∷ ys , zs)
324
+ splitAt (suc n) (x ∷ xs) = Prod.map₁ (x ∷_) (splitAt n xs)
325
+
326
+ -- The following are functions which split a list up using boolean
327
+ -- predicates. However, in practice they are difficult to use and
328
+ -- prove properties about, and are mainly provided for advanced use
329
+ -- cases where one wants to minimise dependencies. In most cases
330
+ -- you probably want to use the versions defined below based on
331
+ -- decidable predicates. e.g. use `takeWhile (_≤? 10) xs`
332
+ -- instead of `takeWhileᵇ (_≤ᵇ 10) xs`
333
+
334
+ takeWhileᵇ : (A → Bool) → List A → List A
335
+ takeWhileᵇ p [] = []
336
+ takeWhileᵇ p (x ∷ xs) = if p x then x ∷ takeWhileᵇ p xs else []
337
+
338
+ dropWhileᵇ : (A → Bool) → List A → List A
339
+ dropWhileᵇ p [] = []
340
+ dropWhileᵇ p (x ∷ xs) = if p x then dropWhileᵇ p xs else x ∷ xs
341
+
342
+ filterᵇ : (A → Bool) → List A → List A
343
+ filterᵇ p [] = []
344
+ filterᵇ p (x ∷ xs) = if p x then x ∷ filterᵇ p xs else filterᵇ p xs
345
+
346
+ partitionᵇ : (A → Bool) → List A → List A × List A
347
+ partitionᵇ p [] = ([] , [])
348
+ partitionᵇ p (x ∷ xs) = (if p x then Prod.map₁ else Prod.map₂′) (x ∷_) (partitionᵇ p xs)
349
+
350
+ spanᵇ : (A → Bool) → List A → List A × List A
351
+ spanᵇ p [] = ([] , [])
352
+ spanᵇ p (x ∷ xs) = if p x
353
+ then Prod.map₁ (x ∷_) (spanᵇ p xs)
354
+ else ([] , x ∷ xs)
355
+
356
+ breakᵇ : (A → Bool) → List A → List A × List A
357
+ breakᵇ p = spanᵇ (not ∘ p)
358
+
359
+ linesByᵇ : (A → Bool) → List A → List (List A)
360
+ linesByᵇ {A = A} p = go nothing
361
+ where
362
+ go : Maybe (List A) → List A → List (List A)
363
+ go acc [] = maybe′ ([_] ∘′ reverse) [] acc
364
+ go acc (c ∷ cs) with p c
365
+ ... | true = reverse (Maybe.fromMaybe [] acc) ∷ go nothing cs
366
+ ... | false = go (just (c ∷ Maybe.fromMaybe [] acc)) cs
367
+
368
+ wordsByᵇ : (A → Bool) → List A → List (List A)
369
+ wordsByᵇ {A = A} p = go []
370
+ where
371
+ cons : List A → List (List A) → List (List A)
372
+ cons [] ass = ass
373
+ cons as ass = reverse as ∷ ass
374
+
375
+ go : List A → List A → List (List A)
376
+ go acc [] = cons acc []
377
+ go acc (c ∷ cs) with p c
378
+ ... | true = cons acc (go [] cs)
379
+ ... | false = go (c ∷ acc) cs
380
+
381
+ derunᵇ : (A → A → Bool) → List A → List A
382
+ derunᵇ r [] = []
383
+ derunᵇ r (x ∷ []) = x ∷ []
384
+ derunᵇ r (x ∷ y ∷ xs) = if r x y
385
+ then derunᵇ r (y ∷ xs)
386
+ else x ∷ derunᵇ r (y ∷ xs)
387
+
388
+ deduplicateᵇ : (A → A → Bool) → List A → List A
389
+ deduplicateᵇ r [] = []
390
+ deduplicateᵇ r (x ∷ xs) = x ∷ filterᵇ (not ∘ r x) (deduplicateᵇ r xs)
391
+
392
+ -- Equivalent functions that use a decidable predicate instead of a
393
+ -- boolean function.
281
394
282
395
takeWhile : ∀ {P : Pred A p} → Decidable P → List A → List A
283
- takeWhile P? [] = []
284
- takeWhile P? (x ∷ xs) with does (P? x)
285
- ... | true = x ∷ takeWhile P? xs
286
- ... | false = []
396
+ takeWhile P? = takeWhileᵇ (does ∘ P?)
287
397
288
398
dropWhile : ∀ {P : Pred A p} → Decidable P → List A → List A
289
- dropWhile P? [] = []
290
- dropWhile P? (x ∷ xs) with does (P? x)
291
- ... | true = dropWhile P? xs
292
- ... | false = x ∷ xs
399
+ dropWhile P? = dropWhileᵇ (does ∘ P?)
293
400
294
401
filter : ∀ {P : Pred A p} → Decidable P → List A → List A
295
- filter P? [] = []
296
- filter P? (x ∷ xs) with does (P? x)
297
- ... | false = filter P? xs
298
- ... | true = x ∷ filter P? xs
402
+ filter P? = filterᵇ (does ∘ P?)
299
403
300
404
partition : ∀ {P : Pred A p} → Decidable P → List A → (List A × List A)
301
- partition P? [] = ([] , [])
302
- partition P? (x ∷ xs) with does (P? x) | partition P? xs
303
- ... | true | (ys , zs) = (x ∷ ys , zs)
304
- ... | false | (ys , zs) = (ys , x ∷ zs)
405
+ partition P? = partitionᵇ (does ∘ P?)
305
406
306
407
span : ∀ {P : Pred A p} → Decidable P → List A → (List A × List A)
307
- span P? [] = ([] , [])
308
- span P? (x ∷ xs) with does (P? x)
309
- ... | true = Prod.map (x ∷_) id (span P? xs)
310
- ... | false = ([] , x ∷ xs)
408
+ span P? = spanᵇ (does ∘ P?)
311
409
312
410
break : ∀ {P : Pred A p} → Decidable P → List A → (List A × List A)
313
- break P? = span (∁? P?)
411
+ break P? = breakᵇ (does ∘ P?)
412
+
413
+ -- The predicate `P` represents the notion of newline character for the
414
+ -- type `A`. It is used to split the input list into a list of lines.
415
+ -- Some lines may be empty if the input contains at least two
416
+ -- consecutive newline characters.
417
+ linesBy : ∀ {P : Pred A p} → Decidable P → List A → List (List A)
418
+ linesBy P? = linesByᵇ (does ∘ P?)
419
+
420
+ -- The predicate `P` represents the notion of space character for the
421
+ -- type `A`. It is used to split the input list into a list of words.
422
+ -- All the words are non empty and the output does not contain any space
423
+ -- characters.
424
+ wordsBy : ∀ {P : Pred A p} → Decidable P → List A → List (List A)
425
+ wordsBy P? = wordsByᵇ (does ∘ P?)
314
426
315
427
derun : ∀ {R : Rel A p} → B.Decidable R → List A → List A
316
- derun R? [] = []
317
- derun R? (x ∷ []) = x ∷ []
318
- derun R? (x ∷ y ∷ xs) with does (R? x y) | derun R? (y ∷ xs)
319
- ... | true | ys = ys
320
- ... | false | ys = x ∷ ys
428
+ derun R? = derunᵇ (does ∘₂ R?)
321
429
322
430
deduplicate : ∀ {R : Rel A p} → B.Decidable R → List A → List A
323
- deduplicate R? [] = []
324
- deduplicate R? (x ∷ xs) = x ∷ filter (¬? ∘ R? x) (deduplicate R? xs)
431
+ deduplicate R? = deduplicateᵇ (does ∘₂ R?)
325
432
326
433
------------------------------------------------------------------------
327
434
-- Actions on single elements
@@ -340,28 +447,6 @@ _─_ : (xs : List A) → Fin (length xs) → List A
340
447
(x ∷ xs) ─ suc k = x ∷ (xs ─ k)
341
448
342
449
------------------------------------------------------------------------
343
- -- Operations for reversing lists
344
-
345
- reverseAcc : List A → List A → List A
346
- reverseAcc = foldl (flip _∷_)
347
-
348
- reverse : List A → List A
349
- reverse = reverseAcc []
350
-
351
- -- "Reverse append" xs ʳ++ ys = reverse xs ++ ys
352
-
353
- infixr 5 _ʳ++_
354
-
355
- _ʳ++_ : List A → List A → List A
356
- _ʳ++_ = flip reverseAcc
357
-
358
- -- Snoc: Cons, but from the right.
359
-
360
- infixl 6 _∷ʳ_
361
-
362
- _∷ʳ_ : List A → A → List A
363
- xs ∷ʳ x = xs ++ [ x ]
364
-
365
450
-- Conditional versions of cons and snoc
366
451
367
452
infixr 5 _?∷_
@@ -373,59 +458,6 @@ _∷ʳ?_ : List A → Maybe A → List A
373
458
xs ∷ʳ? x = maybe′ (xs ∷ʳ_) xs x
374
459
375
460
376
- -- Backwards initialisation
377
-
378
- infixl 5 _∷ʳ′_
379
-
380
- data InitLast {A : Set a} : List A → Set a where
381
- [] : InitLast []
382
- _∷ʳ′_ : (xs : List A) (x : A) → InitLast (xs ∷ʳ x)
383
-
384
- initLast : (xs : List A) → InitLast xs
385
- initLast [] = []
386
- initLast (x ∷ xs) with initLast xs
387
- ... | [] = [] ∷ʳ′ x
388
- ... | ys ∷ʳ′ y = (x ∷ ys) ∷ʳ′ y
389
-
390
- -- uncons, but from the right
391
- unsnoc : List A → Maybe (List A × A)
392
- unsnoc as with initLast as
393
- ... | [] = nothing
394
- ... | xs ∷ʳ′ x = just (xs , x)
395
-
396
- ------------------------------------------------------------------------
397
- -- Splitting a list
398
-
399
- -- The predicate `P` represents the notion of newline character for the type `A`
400
- -- It is used to split the input list into a list of lines. Some lines may be
401
- -- empty if the input contains at least two consecutive newline characters.
402
-
403
- linesBy : ∀ {P : Pred A p} → Decidable P → List A → List (List A)
404
- linesBy {A = A} P? = go nothing where
405
-
406
- go : Maybe (List A) → List A → List (List A)
407
- go acc [] = maybe′ ([_] ∘′ reverse) [] acc
408
- go acc (c ∷ cs) with does (P? c)
409
- ... | true = reverse (Maybe.fromMaybe [] acc) ∷ go nothing cs
410
- ... | false = go (just (c ∷ Maybe.fromMaybe [] acc)) cs
411
-
412
- -- The predicate `P` represents the notion of space character for the type `A`.
413
- -- It is used to split the input list into a list of words. All the words are
414
- -- non empty and the output does not contain any space characters.
415
-
416
- wordsBy : ∀ {P : Pred A p} → Decidable P → List A → List (List A)
417
- wordsBy {A = A} P? = go [] where
418
-
419
- cons : List A → List (List A) → List (List A)
420
- cons [] ass = ass
421
- cons as ass = reverse as ∷ ass
422
-
423
- go : List A → List A → List (List A)
424
- go acc [] = cons acc []
425
- go acc (c ∷ cs) with does (P? c)
426
- ... | true = cons acc (go [] cs)
427
- ... | false = go (c ∷ acc) cs
428
-
429
461
------------------------------------------------------------------------
430
462
-- DEPRECATED
431
463
------------------------------------------------------------------------
0 commit comments