Sequences in F#
Contents
A sequence is a list of potential values (all of them of the same type) computed on demand.
Sequence creation
As with arrays there are several ways to create a sequence.
Create from a range expression
You can create a new sequence from a range expression. In this case, instead of using [|
and |]
you should use {
and }
|
|
Create from a sequence expression
You can use an expression inside brackets (and after seq keyword) to create a new sequence:
|
|
We can write a compacted version using the forward arrow followed by the value to yield:
|
|
Create using a function in the Seq module
As with arrays, there are some functions in the Seq module to create a sequence.
We can use Seq.init to initialise a sequence of n elements.
|
|
Or we can use initInifinite to create an infinite sequence.
|
|
Finally, we can also create a sequence directly from an IEnumerable
|
|
Operations in Seq module
All the operations we’ve seen in the last article about arrays are applicable to this one, changing Array by Seq (i.e. from Array.iter to Seq.iter) and the behavior is the same. Let’s see some other functions that can be valuable.
Seq.unfold
Unfold is a way to generate a sequence from a generator function. You can see it as an extension to Seq.initInfinite. The function takes two parameters: the first one is the generator function, which must return an option tuple with the next element of the sequence and the next state value to be passed to the next iteration. The second parameter is the initial state.
For example, if we want to generate the square of a number up to a certain threshold we can do something like this
|
|
The first 1 is the initial state, in this case 1. This initial state is passed to unfold function. The generator checks if the result will be greater than the threshold and, if it is, returns None. If it isn’t, returns a tuple with the next element of the sequence (in this case de square) and the next state to be passed to unfold (in this case the next number).
Seq.find
Find takes a boolean as a parameter and returns the first element of the sequence that where the function returns true. If it can’t find any result, returns an exception.
Following the previous example if we do
|
|
We get the following error System.Collections.Generic.KeyNotFoundException: Exception of type ‘System.Collections.Generic.KeyNotFoundException’ was thrown.
On the other hand, if we do
|
|
We get
|
|
If we don’t want to get an exception, we can use the tryFind function, which returns an option type. Then, the follwing code
|
|
Returns
|
|
Seq.pick
Given a sequence takes the first result of the function provided as a parameter that is not a None (the function must return an option)
|
|
If there isn’t any valid value, it throws an exception. If you want to avoid this, use tryPick.
Seq.findIndex
Same as Seq.find but returns the index of the element, not the element itself. If you want to avoid the exception, use tryFindIndex.
|
|
Seq.exists
Returns true if the function supplied returns true for any of the values of the sequence.
|
|
Seq.groupBy
Groups a sequence by the results of the function supplied. Returns sequence of key/value pairs.
|
|
Seq.disctint
Given a sequence, return only the unique elements
|
|
If we need to get the disctint elements given a function, we can use disctintBy
Seq.pairwise
Given a sequence creates a sequence of tuples. The first tuple will contain the first and second element of the original sequence, the second tuple will contain the second and third, and so on.
|
|
Seq.windowed
Given a sequence creates a sequence of arrays of the length supplied. The first array will contain the elements between the first element of the original sequence and length. The second one will contain the elements between the second element of the original sequence and length + 1, and so on.
|
|
Seq.collect
Given a sequences applies a function to each element that creates a sequence and concatenates the results:
|
|
Summary
In this article, we’ve continued taking a look at data structures in F#, in this case sequences. We’ve seen some other functions that can also be applied to other data structures.
Author Vicenç García
LastMod 01-01-0001