All Downloads are FREE. Search and download functionalities are using the official Maven repository.

scalaz.effect.RegionT.scala Maven / Gradle / Ivy

package scalaz
package effect

import Kleisli._

// An implementation of "Lightweight Monadic Regions" by Kiselyov and Shan
// http://okmij.org/ftp/Haskell/regions.html#light-weight
// Based on a Haskell library by Bas van Dijk

/**
 * A monad transformer in which scarce resources can be opened. When the region
 * terminates, all opened resources will be closed automatically. It's a type error
 * to return an opened resource from the region, and no I/O with closed
 * resources is possible.
 */
sealed abstract class RegionT[S, P[_], A] {
  def value: Kleisli[P, IORef[List[RefCountedFinalizer]], A]

  def runT(r: IORef[List[RefCountedFinalizer]]): P[A] =
    value.run(r)

  def mapT[Q[_], B](f: P[A] => Q[B]): RegionT[S, Q, B] =
    RegionT(Kleisli(f compose runT))
}

object RegionT extends RegionTInstances {
  def apply[S, P[_], A](k: Kleisli[P, IORef[List[RefCountedFinalizer]], A]): RegionT[S, P, A] = new RegionT[S, P, A] {
    val value = k
  }

  def regionT[S, P[_], A](k: Kleisli[P, IORef[List[RefCountedFinalizer]], A]): RegionT[S, P, A] = RegionT(k)

}

sealed abstract class RegionTInstances1 {
  implicit def RegionTLiftIO[S, M[_]](implicit M: LiftIO[M]): LiftIO[RegionT[S, M, ?]] = new RegionTLiftIO[S, M] {
    implicit def L = M
  }

  implicit def RegionTMonad[S, M[_]](implicit M0: Monad[M]): Monad[RegionT[S, M, ?]] = new RegionTMonad[S, M] {
    implicit def M = M0
  }

  implicit def RegionTHoist[S] = new Hoist[λ[(α[_], β) => RegionT[S, α, β]]] {
    def hoist[M[_]: Monad, N[_]](f: M ~> N) =
      new (RegionT[S, M, ?] ~> RegionT[S, N, ?]) {
        override def apply[B](fa: RegionT[S, M, B]): RegionT[S, N, B] =
          RegionT(Kleisli(r => f.apply(fa.runT(r))))
      }

      override def liftM[M[_]: Monad, B](a: M[B]): RegionT[S, M, B] =
        RegionT(Kleisli(r => a))

      override implicit def apply[M[_]: Monad]: Monad[RegionT[S, M, ?]] =
        RegionTMonad[S, M]
  }

}

sealed abstract class RegionTInstances extends RegionTInstances1 {
}

trait RegionTMonad[S, M[_]] extends Monad[RegionT[S, M, ?]] {
  implicit def M: Monad[M]

  def point[A](a: => A): RegionT[S, M, A] = RegionT(kleisli(s => M.point(a)))
  def bind[A, B](fa: RegionT[S, M, A])(f: A => RegionT[S, M, B]): RegionT[S, M, B] =
    RegionT(kleisli(s => M.bind(fa.value.run(s))((a: A) => f(a).value.run(s))))
}

trait RegionTLiftIO[S, M[_]] extends LiftIO[RegionT[S, M, ?]] {
  implicit def L: LiftIO[M]

  def liftIO[A](ioa: IO[A]) = RegionT.regionT(kleisli(_ => L.liftIO(ioa)))
}





© 2015 - 2025 Weber Informatics LLC | Privacy Policy