Just for more data points (not proposing anything), perhaps look at how C++ handles iterables I'll only be referencing the immutable iterator types or the types that can be immutable based on their contained types, I'll also be using the C++ names for them rather than the more traditional OCaml'y/Haskell'y or so names as C++'s is more expressive due to having more 'types':
* Iterator: This defines something is an iterator, however it has no way to actually iterate it, it is only a marker trait that says that something is some type of iterator
* InputIterator: This is something that you can 'get' something out of, then 'next' to the next element until it 'ends' (or does not end, it could be infinite). You cannot go back over an iteration, it is consume-once thus it is read-once, and you cannot write an element, even of the slot that you are in. The only real Elixir/Erlang 'InputIterator' that I can think of off the top of my mind is the process mailbox.
* OutputIterator: This is something that you can 'put' something in to, then next to the next 'slot' to put something in to it as well. You cannot read from an element even of the slot that you are currently in nor can you write to an element multiple times, only once. The only real Elixir/Erlang 'OutputIterator' that I can think of is sending a message to a process.
* ForwardIterator: Every ForwardIterator is also an InputIterator and/or an OutputIterator (depending on its contained types), you can get/put and next, however unlike InputIterator/OutputIterator you can read/write from/to a slot multiple times and you can also hold a cursor to a given slot to read/write from/to it again even after you have 'next'/iterated past it. You cannot iterate backwards from a given slot, only forwards. This would be like iterating through a list in Elixir/Erlang.
* BidirectionalIterator: Every BidirectionalIterator is also a ForwardIterator, except you can also go backwards from a slot. In Elixir/Erlang this would be like a zipper structure.
* RandomAccessIterator: Every RandomAccessIterator is also a BidirectionalIterator except that you can jump to any slot in *constant* time via an index. An Elixir equivalent would be like accessing a tuple.
C++ also has traits that define if something is a type of container, these are:
* Container: The base Container trait (do note, these are not C++ classes, they are 'traits', if something implements the required functions for their type then they are considered to fulfill a given 'trait', there is no inheritence or anything of the sort). This defines something that 'manages' something else. It has a way to acquire a ForwardIterator (or anything else that implements a ForwardIterator, such as a Bidirectionaliterator). This is like an Elixir list or a map or really anything that holds something.
* ReversibleContainer: A ReversibleContainer must also be a Container. It adds the constraints that acquiring an iterator must return an iterator that fulfills a Bidirectionaliterator in capability. It also adds the constraint that it must be possible to get an iterator that iterates over the elements in reverse order. This is like an Elixir zipper.
* AllocatorAwareContainer: An AllocatorAwareContainer must also be a Container. It is a container that creates it's own elements via a (either passed in or internal) allocator function instead of the user supplying the element. This is like an Elixir Stream.
* SequenceContainer: A SequenceContainer must also be a Container. It adds the constraints that the returned iterator must be in a linear arrangement, such as getting different iterators on the same container must always result in the same order and in constant iteration time (thus that 'next' is constant time). This is like iterating over an Elixir List but not a map.
* ContiguousContainer: A ContiguousContainer must also be a Container. It adds the constraint that the returned iterator must be of type RandomAccessIterator, thus allowing for constant time element access. This is like an Elixir tuple.
A given iterator can fulfill multiple even disjoint iterator traits, like being both an input and an output iterator (in Elixir this would be like a File access interface).
A given container can fulfill multiple container traits, like being both a SequenceContainer and a ContiguousContainer, which in Elixir would be a tuple since it fulfills both requirements.
Just putting it out there that there are a lot of different kinds of Sequences, and even in C++ you cannot know if an iterator (or even a container) is not 'infinite'. Like take stdin/stdout in C++, those are InputIterator and OutputIterator respectively, yet you do not know if either 'end' until you next() on them and test (and 'next()ing' on the stdin InputIterator may 'wait' in time until more input comes in for example, and writing to an OutputIterator of stdout may 'wait' in time if the buffer is full and the receiving pipe has not processed the buffered data yet, which can also happen when sending/receiving message on the BEAM as well).