It’s not all that difficult to also generate permutations lazily:
0..99
|> Stream.flat_map(fn noun -> Stream.map(0..99, &{noun, &1}) end)
My first version used this approach, but then I decided to switch to for
b/c I think it communicates the intention a bit better.