@@ -23,11 +23,11 @@ open import Data.These.Base as These using (These; this; that; these)
2323open import Function.Base
2424 using (id; _∘_ ; _∘′_; _∘₂_; _$_; const; flip)
2525open import Level using (Level)
26- open import Relation.Nullary.Decidable.Core using (does; ¬?)
2726open import Relation.Unary using (Pred; Decidable)
2827open import Relation.Binary.Core using (Rel)
2928import Relation.Binary.Definitions as B
3029open import Relation.Binary.PropositionalEquality.Core using (_≡_)
30+ open import Relation.Nullary.Decidable.Core using (T?; does; ¬?)
3131
3232private
3333 variable
@@ -346,141 +346,160 @@ removeAt : (xs : List A) → Fin (length xs) → List A
346346removeAt (x ∷ xs) zero = xs
347347removeAt (x ∷ xs) (suc i) = x ∷ removeAt xs i
348348
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 = []
356375
357376takeWhileᵇ : (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
360384
361385dropWhileᵇ : (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
364393
365394filterᵇ : (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)
368402
369403partitionᵇ : (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+
372412
373413spanᵇ : (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? )
378418
379419breakᵇ : (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
381428
382- linesByᵇ : (A → Bool) → List A → List (List A)
383- linesByᵇ {A = A} p = go nothing
384- where
385429 go : Maybe (List A) → List A → List (List A)
386430 go acc [] = maybe′ ([_] ∘′ reverse) [] acc
387- go acc (c ∷ cs) with p c
431+ go acc (c ∷ cs) with does (P? c)
388432 ... | true = reverse (Maybe.fromMaybe [] acc) ∷ go nothing cs
389433 ... | false = go (just (c ∷ Maybe.fromMaybe [] acc)) cs
390434
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+
394445 cons : List A → List (List A) → List (List A)
395446 cons [] ass = ass
396447 cons as ass = reverse as ∷ ass
397448
398449 go : List A → List A → List (List A)
399450 go acc [] = cons acc []
400- go acc (c ∷ cs) with p c
451+ go acc (c ∷ cs) with does (P? c)
401452 ... | true = cons acc (go [] cs)
402453 ... | false = go (c ∷ acc) cs
403454
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+
404465derunᵇ : (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)
410471
411472deduplicateᵇ : (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)
414474
415475-- 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+
416480findᵇ : (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)
419482
420483-- 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)
424487 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)
426492
427493-- 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)
431497 then zero ∷ indices
432498 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)
443500
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)
484503
485504------------------------------------------------------------------------
486505-- Actions on single elements
0 commit comments