Skip to content

Commit

Permalink
Merge pull request #4220 from bio-aeon/add-uuidgen-optiont-materializer
Browse files Browse the repository at this point in the history
Add `UUIDGen` inductive materializers for monad transformers
  • Loading branch information
armanbilge authored Jan 2, 2025
2 parents 0cb794b + 6495734 commit a49a028
Showing 1 changed file with 88 additions and 3 deletions.
91 changes: 88 additions & 3 deletions std/shared/src/main/scala/cats/effect/std/UUIDGen.scala
Original file line number Diff line number Diff line change
Expand Up @@ -16,29 +16,107 @@

package cats.effect.std

import cats.Functor
import cats.{~>, Applicative, Functor, Monoid}
import cats.data.{
EitherT,
IndexedReaderWriterStateT,
IndexedStateT,
IorT,
Kleisli,
OptionT,
WriterT
}
import cats.implicits._

import java.util.UUID

/**
* A purely functional UUID Generator
*/
trait UUIDGen[F[_]] {
trait UUIDGen[F[_]] { self =>

/**
* Generates a UUID in a pseudorandom manner.
* @return
* randomly generated UUID
*/
def randomUUID: F[UUID]

/**
* Modifies the context in which this [[UUIDGen]] operates using the natural transformation
* `f`.
*
* @return
* a [[UUIDGen]] in the new context obtained by mapping the current one using `f`
*/
def mapK[G[_]](f: F ~> G): UUIDGen[G] =
new UUIDGen.TranslatedUUIDGen[F, G](self)(f)
}

object UUIDGen extends UUIDGenCompanionPlatform {
def apply[F[_]](implicit ev: UUIDGen[F]): UUIDGen[F] = ev

def randomUUID[F[_]: UUIDGen]: F[UUID] = UUIDGen[F].randomUUID
def randomString[F[_]: UUIDGen: Functor]: F[String] = randomUUID.map(_.toString)
def randomString[F[_]](implicit gen: UUIDGen[F], F: Functor[F]): F[String] =
randomUUID(gen).map(_.toString)

/**
* [[UUIDGen]] instance built for `cats.data.EitherT` values initialized with any `F` data
* type that also implements `UUIDGen`.
*/
implicit def catsEitherTUUIDGen[F[_]: UUIDGen: Functor, L]: UUIDGen[EitherT[F, L, *]] =
UUIDGen[F].mapK(EitherT.liftK)

/**
* [[UUIDGen]] instance built for `cats.data.Kleisli` values initialized with any `F` data
* type that also implements `UUIDGen`.
*/
implicit def catsKleisliUUIDGen[F[_]: UUIDGen, R]: UUIDGen[Kleisli[F, R, *]] =
UUIDGen[F].mapK(Kleisli.liftK)

/**
* [[UUIDGen]] instance built for `cats.data.OptionT` values initialized with any `F` data
* type that also implements `UUIDGen`.
*/
implicit def catsOptionTUUIDGen[F[_]: UUIDGen: Functor]: UUIDGen[OptionT[F, *]] =
UUIDGen[F].mapK(OptionT.liftK)

/**
* [[UUIDGen]] instance built for `cats.data.IndexedStateT` values initialized with any `F`
* data type that also implements `UUIDGen`.
*/
implicit def catsIndexedStateTUUIDGen[F[_]: UUIDGen: Applicative, S]
: UUIDGen[IndexedStateT[F, S, S, *]] =
UUIDGen[F].mapK(IndexedStateT.liftK)

/**
* [[UUIDGen]] instance built for `cats.data.WriterT` values initialized with any `F` data
* type that also implements `UUIDGen`.
*/
implicit def catsWriterTUUIDGen[
F[_]: UUIDGen: Applicative,
L: Monoid
]: UUIDGen[WriterT[F, L, *]] =
UUIDGen[F].mapK(WriterT.liftK)

/**
* [[UUIDGen]] instance built for `cats.data.IorT` values initialized with any `F` data type
* that also implements `UUIDGen`.
*/
implicit def catsIorTUUIDGen[F[_]: UUIDGen: Functor, L]: UUIDGen[IorT[F, L, *]] =
UUIDGen[F].mapK(IorT.liftK)

/**
* [[UUIDGen]] instance built for `cats.data.IndexedReaderWriterStateT` values initialized
* with any `F` data type that also implements `UUIDGen`.
*/
implicit def catsIndexedReaderWriterStateTUUIDGen[
F[_]: UUIDGen: Applicative,
E,
L: Monoid,
S
]: UUIDGen[IndexedReaderWriterStateT[F, E, L, S, S, *]] =
UUIDGen[F].mapK(IndexedReaderWriterStateT.liftK)

implicit def fromSecureRandom[F[_]: Functor: SecureRandom]: UUIDGen[F] =
new UUIDGen[F] {
Expand All @@ -59,4 +137,11 @@ object UUIDGen extends UUIDGenCompanionPlatform {
new UUID(msb, lsb)
}
}

private[std] final class TranslatedUUIDGen[F[_], G[_]](self: UUIDGen[F])(f: F ~> G)
extends UUIDGen[G] {
override def randomUUID: G[UUID] =
f(self.randomUUID)

}
}

0 comments on commit a49a028

Please sign in to comment.