I think that the confusion may arise from the fact that collections like List<T>
implement the interface IEnumerable<T>
. If you have a subtype relationship in general (e.g. supertype Shape
with two subtypes Rectangle
and Circle
), you can interpret the relation as an "is-a" hierarchy.
This means that it is perfectly fine to say that "Circle
is a Shape
" and similarly, people would say that "List<T>
is an IEnumerable<T>
" that is, "list is a sequence". This makes some sense, because a list is a special type of a sequence. In general, sequences can be also lazily generated and infinite (and these types cannot also be lists). An example of a (perfectly valid) sequence that cannot be generated by a list would look like this:
// C# version // F# version
IEnumerable<int> Numbers() { let rec loop n = seq {
int i = 0; yield n
while (true) yield return i++; yield! loop(n + 1) }
} let numbers = loop(0)
This would be also true for F#, because F# list
type also implements IEnumerable<T>
, but functional programming doesn't put that strong emphasis on object oriented point of view (and implicit conversions that enable the "is a" interpretation are used less frequently in F#).