Created
September 18, 2013 22:50
-
-
Save sam/6616857 to your computer and use it in GitHub Desktop.
Scalaz's Applicative Functor for Futures.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Zip together a couple Futures, including one that returns an Option | |
// and pass them to a function to give me a new object: | |
api.channels.tree zip api.pages.getByRoute(route) map { | |
case (tree, Some(page)) => Some(new PagePresenter(context, tree, page)) | |
case _ => None | |
} | |
// Now with an Applicative Functor! | |
(api.channels.tree |@| api.pages.getByRoute(route)) { | |
case (tree, Some(page)) => Some(new PagePresenter(context, tree, page)) | |
case _ => None | |
} | |
// Note the Partial Functions above are the same: | |
// | |
// (Channel, Option[Page]) => Option[PagePresenter] | |
// Ok, whatever. We saved a few characters. But wait! There's more! | |
api.channels.tree zip api.photos.all zip api.photos.getBySlug(slug)) map { | |
case ((tree, photos), Some(photo)) => Some(new PhotoPresenter(context, tree, photos, photo)) | |
case _ => None | |
} | |
// And the Applicative Functor version now: | |
(api.channels.tree |@| api.photos.all |@| api.photos.getBySlug(slug)) { | |
case (tree, photos, Some(photo)) => Some(new PhotoPresenter(context, tree, photos, photo)) | |
case _ => None | |
} | |
// But now we see something else. The zipped version says: zip[A,B]. So after the | |
// first zip you get Future[(A,B)]. Cool. But on the second you get Future[((A,B),C)] | |
// since you're calling zip[(A,B), C] on Future[(A,B)]! Which means our Partial Function | |
// is now: | |
// | |
// ((Channel, Seq[Photo]), Option[Photo]) => Option[PhotoPresenter] | |
// | |
// Instead of the prettier version the Applicative gets to use: | |
// | |
// (Channel, Seq[Photo], Option[Photo]) => Option[PhotoPresenter] | |
// | |
// Visually I'll admit it's not the end of the world. A few extra parenthesis. But think | |
// about what it actually *means*. Especially since you're working with Tuples. | |
// | |
// Zipped: Tuple2[Tuple2[Channel, Seq[Photo]], Option[Photo]] | |
// | |
// Applicative: Tuple3[Channel, Seq[Photo], Option[Photo]] | |
// | |
// Now doesn't that just look better? | |
// But let's go deeper... | |
(api.channels.tree |@| api.channels.getBySlug(slug) |@| | |
api.releases.latest(20) |@| api.releases.count |@| | |
api.photos.latest(20) |@| api.photos.count |@| | |
api.videos.latest(20) |@| api.videos.count) { | |
case (tree, Some(channel), releases, releaseCount, photos, photoCount, videos, videoCount) => | |
Some(new ChannelPresenter(context, tree, channel, releases, releaseCount, photos, photoCount, videos, videoCount)) | |
case _ => None | |
} | |
// So that's a... | |
// | |
// Tuple8[Channel, Option[Channel], Seq[Release], Int, Seq[Photo], Int, Seq[Video], Int] | |
// | |
// Not bad... | |
// Can you imagine the zipped version? No? Well let's try it: | |
api.channels.tree zip api.channels.getBySlug(slug) zip | |
api.releases.latest(20) zip api.releases.count zip | |
api.photos.latest(20) zip api.photos.count zip | |
api.videos.latest(20) zip api.videos.count map { | |
case (((((((tree, Some(channel)), releases), releaseCount), photos), photoCount), videos), videoCount) => | |
Some(new ChannelPresenter(context, tree, channel, releases, releaseCount, photos, photoCount, videos, videoCount)) | |
case _ => None | |
} | |
// I've tried writing the signature out, but it's too wide and I get confused. Going to nest this one: | |
// | |
// Tuple2[ | |
// Tuple2[ | |
// Tuple2[ | |
// Tuple2[ | |
// Tuple2[ | |
// Tuple2[ | |
// Tuple2[ | |
// Channel, | |
// Option[Channel]], | |
// Seq[Release]], | |
// Int], | |
// Seq[Photo]], | |
// Int], | |
// Seq[Video]], | |
// Int] | |
// | |
// Uhmm... I think that's right. Maybe. Eww. | |
// Anyways, scalaz. Applicative Functors. Cool. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment