How to write nested reducibles in Transducers.jl

Writing reducibles · Transducers.jl describes how to make a non-iterable collection reducible; e.g. how to use it as input to transducers. But it does not describe how to delegate the reducing operation to another reducible.

MWE is:

A and B are structs and A contains B:

struct B
    arr::Vector{Int}
end

struct A
    b::B
end

a = A(B([1,2,3,3]))

Then I try to make A and B reducible, such that:

  • folding over A should just fold over the B inside A, and
  • folding over B should just fold over the array in B.

i.e. foldl(op, a) == foldl(op, a.b) == foldl(op, a.b.arr) for some op.

using Transducers

function Transducers.__foldl__(rf, init, a::A) 
    init = foldl(rf, a.b |> Transducers.IdentityTransducer(); init)
    return Transducers.complete(rf, init)
end

function Transducers.__foldl__(rf, init, b::B)
    init = foldl(rf, b.arr; init)
    return Transducers.complete(rf, init)
end

And then:

a.b |> Map(string) |> collect  # works
a |> Map(string) |> collect # works
a.b |> Map(string) |> Unique() |> collect # works
a |> Map(string) |> Unique() |> collect # FAILS?!

It seems that when using Unique() it packs some private state that makes the whole thing go down in flames…
So how should I write my __foldl__ to avoid this? Without resorting to the iterator-based @next pattern…