As part of continuing to learn F# for C# developers, there are several F# Collection Types a programmer must know with their functions.
F# Collection Types
- Seq
- List
- Array
- Map
- Set
After learning the F# collection types, the big question is when should you use one collection type over the other?
Here are several guidelines available that I ran across that might help to decide. Some of the included resources are quite outdated so take it with a grain of salt.
Comparing F# sequences, lists, and arrays (from Get Programming with F# page 184).
Seq | List | Array | |
---|---|---|---|
Eager/Lazy | Lazy | Eager | Eager |
Forward-only | Sometimes | Never | Never |
Immutable | Yes | Yes | No |
Performance | Medium | Medium/High | High |
Pattern matching support | None | Good | Medium |
Interop with C# | Good | Medium | Good |
Seq
Seq is an F# alias for IEnumerable. All functions in the Seq module can operate over IEnumerables.
- Use Seq by default when writing functions, because then they work with any .NET collections.
- When interacting with other .NET languages or libraries that require IEnumerable
. - Need to represent an infinite sequence (probably not really useful in practice).
- Need lazy evaluation.
- Use Seq if you need advanced functions like Seq.windowed or Seq.pairwise.
- You don’t want to hold all elements in memory at the same time.
- Performance is not important.
- You need to do something before and after enumeration, e.g. connect to a database and close connection.
- You are not concatenating (repeated Seq.append will stack overflow).
Tomas Petricek suggested that in general choosing Seq by default would be the best option.
List
- When you need recursive processing using the head::tail patterns.
- When you need a simple immutable data structure that you can build step-by-step.
- Use List when you work with short lists – list is the best data structure to use if the value often represents an empty list, because it is very efficient in that scenario.
- There are few elements.
- You’ll be prepending and decapitating a lot.
(to implement some functionality that’s not available in standard library).
(for example, if you need to process the list on one thread – to show some statistics – and concurrently continue building the list on another thread as you receive more values i.e. from a network service).
Array
- When you need large collections of value types (arrays store data in a flat memory block, so they are more memory efficient in this case).
- When you need random access or more performance (and cache locality).
- Array may be better than Seq or List for parallelism. List is awful for parallel execution due to its sequential nature (head::tail composition).
- Always expose Seq in your public APIs. Use List and Array in internal implementations.
Check out the resources below for more details on F# collection types.
Further Reading
Get Programming with F#
When to use a sequence in F# as opposed to a list?
Choosing between collection functions
F# Collection Types
How to Setup Visual Studio Editor for F#
Leave a Reply