@@ -23,11 +23,11 @@ open import Data.These.Base as These using (These; this; that; these)
23
23
open import Function.Base
24
24
using (id; _∘_ ; _∘′_; _∘₂_; _$_; const; flip)
25
25
open import Level using (Level)
26
- open import Relation.Nullary.Decidable.Core using (does; ¬?)
27
26
open import Relation.Unary using (Pred; Decidable)
28
27
open import Relation.Binary.Core using (Rel)
29
28
import Relation.Binary.Definitions as B
30
29
open import Relation.Binary.PropositionalEquality.Core using (_≡_)
30
+ open import Relation.Nullary.Decidable.Core using (T?; does; ¬?)
31
31
32
32
private
33
33
variable
@@ -346,141 +346,160 @@ removeAt : (xs : List A) → Fin (length xs) → List A
346
346
removeAt (x ∷ xs) zero = xs
347
347
removeAt (x ∷ xs) (suc i) = x ∷ removeAt xs i
348
348
349
- -- The following are functions which split a list up using boolean
350
- -- predicates. However, in practice they are difficult to use and
351
- -- prove properties about, and are mainly provided for advanced use
352
- -- cases where one wants to minimise dependencies. In most cases
353
- -- you probably want to use the versions defined below based on
354
- -- decidable predicates. e.g. use `takeWhile (_≤? 10) xs`
355
- -- instead of `takeWhileᵇ (_≤ᵇ 10) xs`
349
+ ------------------------------------------------------------------------
350
+ -- Operations for filtering lists
351
+
352
+ -- The following are a variety of functions that can be used to
353
+ -- construct sublists using a predicate.
354
+ --
355
+ -- Each function has two forms. The first main variant uses a
356
+ -- proof-relevant decidable predicate, while the second variant uses
357
+ -- a irrelevant boolean predicate and are suffixed with a `ᵇ` character,
358
+ -- typed as \^b.
359
+ --
360
+ -- The decidable versions have several advantages: 1) easier to prove
361
+ -- properties, 2) better meta-variable inference and 3) most of the rest
362
+ -- of the library is set-up to work with decidable predicates. However,
363
+ -- in rare cases the boolean versions can be useful, mainly when one
364
+ -- wants to minimise dependencies.
365
+ --
366
+ -- In summary, in most cases you probably want to use the decidable
367
+ -- versions over the boolean versions, e.g. use `takeWhile (_≤? 10) xs`
368
+ -- rather than `takeWhileᵇ (_≤ᵇ 10) xs`.
369
+
370
+ takeWhile : ∀ {P : Pred A p} → Decidable P → List A → List A
371
+ takeWhile P? [] = []
372
+ takeWhile P? (x ∷ xs) with does (P? x)
373
+ ... | true = x ∷ takeWhile P? xs
374
+ ... | false = []
356
375
357
376
takeWhileᵇ : (A → Bool) → List A → List A
358
- takeWhileᵇ p [] = []
359
- takeWhileᵇ p (x ∷ xs) = if p x then x ∷ takeWhileᵇ p xs else []
377
+ takeWhileᵇ p = takeWhile (T? ∘ p)
378
+
379
+ dropWhile : ∀ {P : Pred A p} → Decidable P → List A → List A
380
+ dropWhile P? [] = []
381
+ dropWhile P? (x ∷ xs) with does (P? x)
382
+ ... | true = dropWhile P? xs
383
+ ... | false = x ∷ xs
360
384
361
385
dropWhileᵇ : (A → Bool) → List A → List A
362
- dropWhileᵇ p [] = []
363
- dropWhileᵇ p (x ∷ xs) = if p x then dropWhileᵇ p xs else x ∷ xs
386
+ dropWhileᵇ p = dropWhile (T? ∘ p)
387
+
388
+ filter : ∀ {P : Pred A p} → Decidable P → List A → List A
389
+ filter P? [] = []
390
+ filter P? (x ∷ xs) with does (P? x)
391
+ ... | false = filter P? xs
392
+ ... | true = x ∷ filter P? xs
364
393
365
394
filterᵇ : (A → Bool) → List A → List A
366
- filterᵇ p [] = []
367
- filterᵇ p (x ∷ xs) = if p x then x ∷ filterᵇ p xs else filterᵇ p xs
395
+ filterᵇ p = filter (T? ∘ p)
396
+
397
+ partition : ∀ {P : Pred A p} → Decidable P → List A → (List A × List A)
398
+ partition P? [] = ([] , [])
399
+ partition P? (x ∷ xs) with does (P? x) | partition P? xs
400
+ ... | true | (ys , zs) = (x ∷ ys , zs)
401
+ ... | false | (ys , zs) = (ys , x ∷ zs)
368
402
369
403
partitionᵇ : (A → Bool) → List A → List A × List A
370
- partitionᵇ p [] = ([] , [])
371
- partitionᵇ p (x ∷ xs) = (if p x then Prod.map₁ else Prod.map₂′) (x ∷_) (partitionᵇ p xs)
404
+ partitionᵇ p = partition (T? ∘ p)
405
+
406
+ span : ∀ {P : Pred A p} → Decidable P → List A → (List A × List A)
407
+ span P? [] = ([] , [])
408
+ span P? ys@(x ∷ xs) with does (P? x)
409
+ ... | true = Prod.map (x ∷_) id (span P? xs)
410
+ ... | false = ([] , ys)
411
+
372
412
373
413
spanᵇ : (A → Bool) → List A → List A × List A
374
- spanᵇ p [] = ([] , [] )
375
- spanᵇ p (x ∷ xs) = if p x
376
- then Prod.map₁ (x ∷_) (spanᵇ p xs )
377
- else ([] , x ∷ xs )
414
+ spanᵇ p = span (T? ∘ p )
415
+
416
+ break : ∀ {P : Pred A p} → Decidable P → List A → (List A × List A )
417
+ break P? = span (¬? ∘ P? )
378
418
379
419
breakᵇ : (A → Bool) → List A → List A × List A
380
- breakᵇ p = spanᵇ (not ∘ p)
420
+ breakᵇ p = break (T? ∘ p)
421
+
422
+ -- The predicate `P` represents the notion of newline character for the
423
+ -- type `A`. It is used to split the input list into a list of lines.
424
+ -- Some lines may be empty if the input contains at least two
425
+ -- consecutive newline characters.
426
+ linesBy : ∀ {P : Pred A p} → Decidable P → List A → List (List A)
427
+ linesBy {A = A} P? = go nothing where
381
428
382
- linesByᵇ : (A → Bool) → List A → List (List A)
383
- linesByᵇ {A = A} p = go nothing
384
- where
385
429
go : Maybe (List A) → List A → List (List A)
386
430
go acc [] = maybe′ ([_] ∘′ reverse) [] acc
387
- go acc (c ∷ cs) with p c
431
+ go acc (c ∷ cs) with does (P? c)
388
432
... | true = reverse (Maybe.fromMaybe [] acc) ∷ go nothing cs
389
433
... | false = go (just (c ∷ Maybe.fromMaybe [] acc)) cs
390
434
391
- wordsByᵇ : (A → Bool) → List A → List (List A)
392
- wordsByᵇ {A = A} p = go []
393
- where
435
+ linesByᵇ : (A → Bool) → List A → List (List A)
436
+ linesByᵇ p = linesBy (T? ∘ p)
437
+
438
+ -- The predicate `P` represents the notion of space character for the
439
+ -- type `A`. It is used to split the input list into a list of words.
440
+ -- All the words are non empty and the output does not contain any space
441
+ -- characters.
442
+ wordsBy : ∀ {P : Pred A p} → Decidable P → List A → List (List A)
443
+ wordsBy {A = A} P? = go [] where
444
+
394
445
cons : List A → List (List A) → List (List A)
395
446
cons [] ass = ass
396
447
cons as ass = reverse as ∷ ass
397
448
398
449
go : List A → List A → List (List A)
399
450
go acc [] = cons acc []
400
- go acc (c ∷ cs) with p c
451
+ go acc (c ∷ cs) with does (P? c)
401
452
... | true = cons acc (go [] cs)
402
453
... | false = go (c ∷ acc) cs
403
454
455
+ wordsByᵇ : (A → Bool) → List A → List (List A)
456
+ wordsByᵇ p = wordsBy (T? ∘ p)
457
+
458
+ derun : ∀ {R : Rel A p} → B.Decidable R → List A → List A
459
+ derun R? [] = []
460
+ derun R? (x ∷ []) = x ∷ []
461
+ derun R? (x ∷ xs@(y ∷ _)) with does (R? x y) | derun R? xs
462
+ ... | true | ys = ys
463
+ ... | false | ys = x ∷ ys
464
+
404
465
derunᵇ : (A → A → Bool) → List A → List A
405
- derunᵇ r [] = []
406
- derunᵇ r (x ∷ []) = x ∷ []
407
- derunᵇ r (x ∷ y ∷ xs) = if r x y
408
- then derunᵇ r (y ∷ xs)
409
- else x ∷ derunᵇ r (y ∷ xs)
466
+ derunᵇ r = derun (T? ∘₂ r)
467
+
468
+ deduplicate : ∀ {R : Rel A p} → B.Decidable R → List A → List A
469
+ deduplicate R? [] = []
470
+ deduplicate R? (x ∷ xs) = x ∷ filter (¬? ∘ R? x) (deduplicate R? xs)
410
471
411
472
deduplicateᵇ : (A → A → Bool) → List A → List A
412
- deduplicateᵇ r [] = []
413
- deduplicateᵇ r (x ∷ xs) = x ∷ filterᵇ (not ∘ r x) (deduplicateᵇ r xs)
473
+ deduplicateᵇ r = deduplicate (T? ∘₂ r)
414
474
415
475
-- Finds the first element satisfying the boolean predicate
476
+ find : ∀ {P : Pred A p} → Decidable P → List A → Maybe A
477
+ find P? [] = nothing
478
+ find P? (x ∷ xs) = if does (P? x) then just x else find P? xs
479
+
416
480
findᵇ : (A → Bool) → List A → Maybe A
417
- findᵇ p [] = nothing
418
- findᵇ p (x ∷ xs) = if p x then just x else findᵇ p xs
481
+ findᵇ p = find (T? ∘ p)
419
482
420
483
-- Finds the index of the first element satisfying the boolean predicate
421
- findIndexᵇ : (A → Bool) → (xs : List A) → Maybe $ Fin (length xs)
422
- findIndexᵇ p [] = nothing
423
- findIndexᵇ p (x ∷ xs) = if p x
484
+ findIndex : ∀ {P : Pred A p} → Decidable P → (xs : List A) → Maybe $ Fin (length xs)
485
+ findIndex P? [] = nothing
486
+ findIndex P? (x ∷ xs) = if does (P? x)
424
487
then just zero
425
- else Maybe.map suc (findIndexᵇ p xs)
488
+ else Maybe.map suc (findIndex P? xs)
489
+
490
+ findIndexᵇ : (A → Bool) → (xs : List A) → Maybe $ Fin (length xs)
491
+ findIndexᵇ p = findIndex (T? ∘ p)
426
492
427
493
-- Finds indices of all the elements satisfying the boolean predicate
428
- findIndicesᵇ : (A → Bool) → (xs : List A) → List $ Fin (length xs)
429
- findIndicesᵇ p [] = []
430
- findIndicesᵇ p (x ∷ xs) = if p x
494
+ findIndices : ∀ {P : Pred A p} → Decidable P → (xs : List A) → List $ Fin (length xs)
495
+ findIndices P? [] = []
496
+ findIndices P? (x ∷ xs) = if does (P? x)
431
497
then zero ∷ indices
432
498
else indices
433
- where indices = map suc (findIndicesᵇ p xs)
434
-
435
- -- Equivalent functions that use a decidable predicate instead of a
436
- -- boolean function.
437
-
438
- takeWhile : ∀ {P : Pred A p} → Decidable P → List A → List A
439
- takeWhile P? = takeWhileᵇ (does ∘ P?)
440
-
441
- dropWhile : ∀ {P : Pred A p} → Decidable P → List A → List A
442
- dropWhile P? = dropWhileᵇ (does ∘ P?)
499
+ where indices = map suc (findIndices P? xs)
443
500
444
- filter : ∀ {P : Pred A p} → Decidable P → List A → List A
445
- filter P? = filterᵇ (does ∘ P?)
446
-
447
- partition : ∀ {P : Pred A p} → Decidable P → List A → (List A × List A)
448
- partition P? = partitionᵇ (does ∘ P?)
449
-
450
- span : ∀ {P : Pred A p} → Decidable P → List A → (List A × List A)
451
- span P? = spanᵇ (does ∘ P?)
452
-
453
- break : ∀ {P : Pred A p} → Decidable P → List A → (List A × List A)
454
- break P? = breakᵇ (does ∘ P?)
455
-
456
- -- The predicate `P` represents the notion of newline character for the
457
- -- type `A`. It is used to split the input list into a list of lines.
458
- -- Some lines may be empty if the input contains at least two
459
- -- consecutive newline characters.
460
- linesBy : ∀ {P : Pred A p} → Decidable P → List A → List (List A)
461
- linesBy P? = linesByᵇ (does ∘ P?)
462
-
463
- -- The predicate `P` represents the notion of space character for the
464
- -- type `A`. It is used to split the input list into a list of words.
465
- -- All the words are non empty and the output does not contain any space
466
- -- characters.
467
- wordsBy : ∀ {P : Pred A p} → Decidable P → List A → List (List A)
468
- wordsBy P? = wordsByᵇ (does ∘ P?)
469
-
470
- derun : ∀ {R : Rel A p} → B.Decidable R → List A → List A
471
- derun R? = derunᵇ (does ∘₂ R?)
472
-
473
- deduplicate : ∀ {R : Rel A p} → B.Decidable R → List A → List A
474
- deduplicate R? = deduplicateᵇ (does ∘₂ R?)
475
-
476
- find : ∀ {P : Pred A p} → Decidable P → List A → Maybe A
477
- find P? = findᵇ (does ∘ P?)
478
-
479
- findIndex : ∀ {P : Pred A p} → Decidable P → (xs : List A) → Maybe $ Fin (length xs)
480
- findIndex P? = findIndexᵇ (does ∘ P?)
481
-
482
- findIndices : ∀ {P : Pred A p} → Decidable P → (xs : List A) → List $ Fin (length xs)
483
- findIndices P? = findIndicesᵇ (does ∘ P?)
501
+ findIndicesᵇ : (A → Bool) → (xs : List A) → List $ Fin (length xs)
502
+ findIndicesᵇ p = findIndices (T? ∘ p)
484
503
485
504
------------------------------------------------------------------------
486
505
-- Actions on single elements
0 commit comments