Traverse and friends with exercises

3 minute read Published: 2019-10-06

I work at a scala shop. Probably the typical scala shop --most people aren't that familiar with scala, certainly not FP, and tend to have Java backgrounds or are on some other team (I'm looking at you go) and have somehow inherited a Scala service. Needless to say I spend a lot of time on education.

Recently I was hit with a whack of questions around dealing with nested types --we can say nested effects here. Nothing crazy but it was tripping up people new to the language and programming with effects like

List[Future[Either[Error, List[Either[Serror, ParsedResponse]]]]]

In this case it was taking some sort of list of requests, chunking them into batches, making some remote call per batch to some external API that supported batched requests. An entire batch may fail or a batch may succeed but individual elements of the returned json array may have failed for one reason or another. People were contorting themselves into knots over this doing what everyone does when they are new (myself included the first time I hit something like this in a job interview):

The real trick is knowing about Travsere and/or sequence. I won't get into the details (but I do give lunchtime workshops on this at work!) other than it's a convienent way to swap two contexts:

// have: List[Option[Int]]
val xs = List(1.some, 2.some, 3.some, 4.some)
// want: Option[List[Int]]
xs.sequence 
// res0: Option[List[Int]]

This works for most containers you would want it to. In the standard library it's really for Futures + Option or List. Cats defines it much more generally.

Sequence is simply travserse(identity). If you find yourself mapping a function and then using sequence you can replace that with a single call to traverse.

Beyond that, working knowledge of monoids is handy especially for how folding a monoid works (.combineAll is so handy).

As a result of all these questions I built out a workshop that I ask people to do. There are five questions around dealing with variations of the above nested type and getting it to some other type with some design decisions along the way:

Give it a whirl --try to make all the tests go green.

The workshop can be found here and the solutions can be found here