Skip to content

Instantly share code, notes, and snippets.

@tpolecat
Created October 6, 2016 17:40
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tpolecat/0fc091d76e40e0c77187a31d5f154cb3 to your computer and use it in GitHub Desktop.
Save tpolecat/0fc091d76e40e0c77187a31d5f154cb3 to your computer and use it in GitHub Desktop.

It's not good enough to abstract Future to M[_]: Monad

Let's get our imports out of the way.

import scala.util.Random.nextInt
import scala.concurrent._
import scala.concurrent.duration._
import scala.concurrent.ExecutionContext.Implicits.global

import scalaz._, Scalaz._
import scalaz.effect.IO
// API specialized to Future
def rndF(n: Int): Future[List[Int]] = {
  val m = Future(nextInt(100))
  Future.sequence(List.fill(n)(m))
}

// API abstracted over Monad (allegedly)
def rnd[M[_]](n: Int)(implicit M: Monad[M]): M[List[Int]] = {
  val m = M.point(nextInt(100))
  List.fill(n)(m).sequence
}

So let's confirm that the behavior is consistent between the implementations when using Future.

scala> Await.result(rndF(10), Duration.Inf)
res6: List[Int] = List(90, 90, 90, 90, 90, 90, 90, 90, 90, 90)

scala> Await.result(rnd[Future](10), Duration.Inf)
res7: List[Int] = List(33, 33, 33, 33, 33, 33, 33, 33, 33, 33)

As expected. Now with Id and Need.

scala> rnd[Id](10)
res8: scalaz.Scalaz.Id[List[Int]] = List(96, 96, 96, 96, 96, 96, 96, 96, 96, 96)

scala> rnd[Need](10).value
res9: List[Int] = List(18, 18, 18, 18, 18, 18, 18, 18, 18, 18)

But what about data types that capture computations rather than values?

scala> rnd[IO](10).unsafePerformIO
res10: List[Int] = List(40, 49, 79, 36, 77, 22, 62, 89, 63, 11)

scala> rnd[Name](10).value
res11: List[Int] = List(96, 66, 69, 86, 0, 51, 4, 85, 30, 56)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment