-
Notifications
You must be signed in to change notification settings - Fork 264
[DRY?] Direct definition vs. generic combinators, ctd. in Algebra.Definitions.RawMonoid #2475
Description
Addition: suggest adding to Data.Vec.Functional.Base
-- Non-empty folds
foldr₁ : (A → A → A) → Vector A (suc n) → A
foldr₁ {n = zero} _⊕_ xs = head xs
foldr₁ {n = suc _} _⊕_ xs = (head xs) ⊕ foldr₁ _⊕_ (tail xs)
foldl₁ : (A → A → A) → Vector A (suc n) → A
foldl₁ _⊕_ xs = foldl _⊕_ (head xs) (tail xs)(and perhaps also retrofitting to Data.Vec.Base, too)
Refactoring: suggest replacing the definitions in Algebra.Definitions.RawMonoid with
sumʳ sumˡ sum : ∀ {n} → Vector Carrier n → Carrier
sumʳ {n = zero} xs = 0#
sumʳ {n = suc _} xs = Vector.foldr₁ _+_ xs
sumˡ {n = zero} xs = 0#
sumˡ {n = suc _} xs = Vector.foldl₁ _+_ xs
sum = Vector.foldr _+_ 0#(with the last one for backwards compatibility; but even for right-associative addition, sumʳ avoids redundancy in the {n = 1} case)
and then also
_×_ : ℕ → Carrier → Carrier
n × x = sum (Vector.replicate n x)
_×′_ : ℕ → Carrier → Carrier
n ×′ x = sumˡ (Vector.replicate n x)(again: using sumʳ in the first definition might be an improvement? although a breaking change...)
BUT as to performance/intensional reduction behaviour:
- it seems that replacing the existing direct definitions of
_×_and_×′_in this way, even with{-# INLINE ... #-}directives, just doesn't quite give the correct unfolding behaviour for the existing proofs inAlgebra.Properties.Monoid.Mult.*to go through properly; - is there some way to achieve this? (eg by more inlining? if so, how/when do we decide what's appropriate;
stdlibseems to be quite sparing in its appeals to such 'extralogical' techniques) - would such a change actually be more efficient in practice than the existing direct definitions?
It seems as though the 'generic' definitions ought to be more robust/reusable/'better' (esp. as Vector.replicate is simply const, so the use of head and tail in the various folds is inlinable/eliminable?), but it just ... doesn't quite seem to work :-(
Any help/insight into how to (understand how to) resolve this trade-off welcome! It feels as though I am missing something fundamental, but possibly non-obvious, about what's going on here.