How to sequence in Rust
Sean Policarpio
Posted on May 21, 2019
Well, I wouldn't say it's exactly the same sequencing in terms of FP languages like Scala et al., but it does the job for the given collection types in Rust; invert something of type F<G<A>>
into G<F<A>>
.
Usually, we'd expect F
and G
as types that are iterable and applicative. In the case of Rust, what I seem to understand from the standard library is that it is expected that there exists a trait implementation—FromIterator
—that should allow G
to be treated like an applicative. Since collect()
is already iterating over a collection of G<A>
, it's straightforward for an implementation of FromIterator
for F
to turn the results (i.e. a collection of them) of the first FromIterator
into a G<F<A>>
—which is what it does.
let opt = vec![Some(1), Some(2), Some(3)];
let sequenced = opt.into_iter().collect::<Option<Vec<i32>>>();
print!("{:?}", sequenced); // Some([1, 2, 3])
let opt = vec![Some(1), None, Some(3)];
let sequenced = opt.into_iter().collect::<Option<Vec<i32>>>();
print!("{:?}", sequenced); // None
let result = vec![Ok(1), Ok(2), Ok(3)];
let sequenced = result.into_iter().collect::<Result<Vec<i32>, &str>>();
print!("{:?}", sequenced); // Ok([1, 2, 3])
let result = vec![Ok(1), Err("oops"), Ok(3)];
let sequenced = result.into_iter().collect::<Result<Vec<i32>, &str>>();
print!("{:?}", sequenced); // Err("oops")
let result = vec![Ok(1), Ok(2), Ok(3)];
let sequenced = result.into_iter().map(|opt_i| opt_i.map(|i| i + 1)).collect::<Result<Vec<i32>, &str>>();
print!("{:?}", sequenced); // Ok([2, 3, 4])
originally posted as a gist.
Posted on May 21, 2019
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.