How to sequence in Rust

kdrakon

Sean Policarpio

Posted on May 21, 2019

How to sequence in Rust

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.

💖 💪 🙅 🚩
kdrakon
Sean Policarpio

Posted on May 21, 2019

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related

How to sequence in Rust
rust How to sequence in Rust

May 21, 2019