I think that a good way to understand transducers is to look at their implementation (shortened a bit). Here it is for map: ([f] (fn [f1] (fn ([result input] (f1 result (f input))) ([result input & inputs] (f1 result (apply f input inputs)))))) filter: ([pred] (fn [f1] (fn ([result input] (if (pred input) (f1 result input) result))))) And it gets more interesting with take: ([n] (fn [f1] (let [na (atom n)] (fn ([resu…
Interesting. Continuing to try to analyze these in Haskell, I think this is a direct translation: -- z is just there to not clobber some standard prelude names type Red r a = r -> a -> r zmap :: (b -> a) -> Red r a -> Red r b zmap f f1 result input = f1 result (f input) zfilt :: (a -> Bool) -> Red r a -> Red r a zfilt p f1 result input = if p input then f1 result input else result ztake :: Int -> Red r a -> (r -> a -…
type Red r a = (r -> a -> r, r)
zmap :: (b -> a) -> Red r a -> Red r b
zmap f (f1, z1) = (\result input -> f1 result (f input), z1)
zfilt :: (a -> Bool) -> Red r a -> Red r a
zfilt p (f1, z1) = (\result input -> if p input then f1 result input else result, z1)
ztake :: Int -> Red r a -> Red r a
ztake n (f1, z1) = (run n, z1) where
run n result input =
let n' = n - 1
result = if n >= 0 then f1 result input else result
in if n' == 0 then z1 else result
This has the theoretical niceness of having `Red r a` just be the signature functor for linked lists.