Advertisement
Guest User

Untitled

a guest
Apr 14th, 2014
183
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Scala 3.18 KB | None | 0 0
  1. package util
  2.  
  3. import language._
  4.  
  5. import scala.concurrent.duration.Duration
  6.  
  7. import scalaz._
  8. import scalaz.effect._
  9. import scalaz.syntax.monad._
  10.  
  11. // note that F[A] === F[TimeoutT[Identity, A]]
  12. final class TimeoutT[F[_], A] private[util] (private[util] val fa: F[A], private[util] val delay: Duration, private[util] val transform: A => TimeoutT[F, A]) {
  13.   private[this] val init = System.currentTimeMillis
  14.  
  15.   def run(implicit FL: LiftIO[F], F: Monad[F]): F[A] = {
  16.     val back = if (delay.isFinite) {
  17.       val check = FL.liftIO(IO { System.currentTimeMillis < init + delay.toMillis })
  18.      
  19.       check flatMap { flag =>
  20.         if (flag)
  21.           fa
  22.         else
  23.           fa flatMap { transform(_).run }
  24.       }
  25.     } else {
  26.       fa
  27.     }
  28.    
  29.     back
  30.   }
  31.  
  32.   def flatMap[B](f: A => TimeoutT[F, B])(implicit FL: LiftIO[F], F: Monad[F]): TimeoutT[F, B] = {
  33.     val fa = run flatMap { fa =>
  34.       f(fa).run
  35.     }
  36.    
  37.     TimeoutT(fa)
  38.   }
  39.  
  40.   def map[B](f: A => B)(implicit FL: LiftIO[F], F: Monad[F]): TimeoutT[F, B] = TimeoutT(run map f)
  41. }
  42.  
  43. object TimeoutT extends TimeoutTInstances {
  44.   def apply[F[_], A](fa: F[A]): TimeoutT[F, A] =
  45.     new TimeoutT(fa, Duration.Inf, { _: A => sys.error("assertion error") })        // definitional failure if we hit this case
  46.  
  47.   def setTimeout[F[_], A](a: F[A], delay: Duration)(transform: A => TimeoutT[F, A]): TimeoutT[F, A] =
  48.     new TimeoutT(a, delay, transform)
  49. }
  50.  
  51. sealed abstract class TimeoutTInstances1 {
  52.   implicit def timeoutTFunctor[F[_], A](implicit FL0: LiftIO[F], F0: Monad[F]): Functor[({ type λ[α] = TimeoutT[F, α] })#λ] = new TimeoutTFunctor[F] {
  53.     def FL = FL0
  54.     def F = F0
  55.   }
  56. }
  57.  
  58. sealed abstract class TimeoutTInstances0 extends TimeoutTInstances1 {
  59.   implicit def timeoutTMonad[F[_], A](implicit FL0: LiftIO[F], F0: Monad[F]): Monad[({ type λ[α] = TimeoutT[F, α] })#λ] = new TimeoutTMonad[F] {
  60.     def FL = FL0
  61.     def F = F0
  62.   }
  63. }
  64.  
  65. sealed abstract class TimeoutTInstances extends TimeoutTInstances0 {
  66.   implicit val timeoutTMonadTrans: Hoist[TimeoutT] = new TimeoutTHoist {}
  67. }
  68.  
  69. private trait TimeoutTFunctor[F[_]] extends Functor[({ type λ[α] = TimeoutT[F, α] })#λ] {
  70.   implicit def FL: LiftIO[F]
  71.   implicit def F: Monad[F]
  72.  
  73.   override def map[A, B](fa: TimeoutT[F, A])(f: A => B): TimeoutT[F, B] = fa map f
  74. }
  75.  
  76. private trait TimeoutTMonad[F[_]] extends Monad[({ type λ[α] = TimeoutT[F, α] })#λ] {
  77.   implicit def FL: LiftIO[F]
  78.   implicit def F: Monad[F]
  79.  
  80.   def point[A](a: => A): TimeoutT[F, A] = TimeoutT(F point a)
  81.  
  82.   def bind[A, B](fa: TimeoutT[F, A])(f: A => TimeoutT[F, B]): TimeoutT[F, B] = fa flatMap f
  83. }
  84.  
  85. private trait TimeoutTHoist extends Hoist[TimeoutT] {
  86.   // monad constraint is actually unnecessary here except to preserve signature
  87.   def liftM[G[_]: Monad, A](a: G[A]): TimeoutT[G, A] = TimeoutT(a)
  88.  
  89.   def hoist[M[_]: Monad, N[_]](f: M ~> N) = new (({ type λ[α] = TimeoutT[M, α] })#λ ~> ({ type λ[α] = TimeoutT[N, α] })#λ) {
  90.     def apply[A](fa: TimeoutT[M, A]): TimeoutT[N, A] = {
  91.       new TimeoutT(f(fa.fa), fa.delay, fa.transform andThen apply)
  92.     }
  93.   }
  94.  
  95.   def apply[G[_]: Monad]: Monad[({ type λ[α] = TimeoutT[G, α] })#λ] = ???
  96. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement