Is it possible to write in haskell something similar to fold functions on many lists. Here is example for such function in Racket
#lang racket
(define (fold-left f i as . bss)
(if (or (null? as)
(ormap null? bss))
i
(apply fold-left
f
(apply f i (car as) (map car bss))
(cdr as)
(map cdr bss))))
(fold-left + 0 (list 1 2 3 4) (list 5 6 7 8))
(fold-left + 0 (list 1 2 3) (list 2 3 4) (list 3 4 5) (list 4 5 6))
(fold-left (λ (i v n s) (string-append i (vector-ref v n) s))
""
(list (vector "A cat" "A dog" "A mouse")
(vector "tuna" "steak" "cheese"))
(list 0 2)
(list " does not eat " "."))
The example uses of fold-left evaluate to 36, 42, and "A cat does not eat cheese.". It seems to me not yet, but perhaps there is some trick that I haven’t thought of?
There's no direct equivalent because that would require creating list with (dynamically) heterogenous types. However, you can still pretty much achieve the same result using other operations in Haskell:
(fold-left + 0 (list 1 2 3 4) (list 5 6 7 8))
Would be sum $ zipWith (+) [1,2,3,4] [5, 6, 7, 8]
(fold-left (λ (i v n s) (string-append i (vector-ref v n) s))
""
(list (vector "A cat" "A dog" "A mouse")
(vector "tuna" "steak" "cheese"))
(list 0 2)
(list " does not eat " "."))
Would be
concat $ zipWith3 (\v n s -> concat [v!!n, s])
[ ["A cat", "A dog", "A mouse"]
, ["tuna", "steak","cheese"]
]
[0, 2]
[" does not eat ", "."]
zipWith3
can be extended to any arbitrary (but fixed, because static typing) number of lists with the Applicative
instance of ZipList
:
zipWith<n> f l1 ... ln === f <$> ZipList l1 <*> ... <*> ZipList ln
So basically, instead of stuffing everything inside one big fold that somehow 'knows' how deep to go, you'd just write out the folds explicitly.