///|
pub fn[T : Eq + Hash] cartesian(arr : Array[Iter[T]]) -> Iter[Iter[T]] {
  let l = arr.length()
  fn go {
    0 => Iter::singleton(Iter::empty())
    i => arr[i - 1].flat_map(fn { x => go(i - 1).map(Iter::append(_, x)) })
  }

  go(l)
}

///|
test {
  inspect(
    cartesian([[1, 2].iter(), [3, 4].iter(), [5, 6].iter()]),
    content="[[1, 3, 5], [2, 3, 5], [1, 4, 5], [2, 4, 5], [1, 3, 6], [2, 3, 6], [1, 4, 6], [2, 4, 6]]",
  )
  inspect(Set::from_array([1, 2]).iter(), content="[1, 2]")
}