The fact that you wrote this comment with Hindley-Milner-ish notation already makes your an outlier.
Associativity also makes fold hard. It's not super trivial to know when you might need e.g. left fold vs right fold
Suppose we have foldr as in [A] -> B -> ((A, B) -> B) -> B, foldl as in [A] -> B -> ((B, A) -> B) -> B, and reduce as in [A] -> ((A, A) -> A) -> A.
Then we have foldr list value operator = reduce [\b -> operator a b | a <- list] (.), foldl list value operator = foldr (reverse list) value (flip operator), and in the case of a finite non-empty list and associative operator, we have reduce list operator = foldr (tail list) (head list) operator = foldl (init list) (last list) operator.
So these are all basically slight re-parametrizations of each other.
You will eventually learn about something called "for loop", and it will be nice.
Indeed, this is why everyone knows the J programming language.
Plus it forces you out of whatever lazy/streaming paradigm you had going on. If your foldr produces a list, downstream can start consuming it in constant memory as long as you let it do its thing.
I.e. there is no initial value to pass in, but the result is an Optional to handle the empty iterator case. That’s how rust does it, for example:
https://doc.rust-lang.org/std/iter/trait.Iterator.html#metho...