Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add higher kinded typeclass instances for Logs #191

Merged
merged 3 commits into from
Mar 10, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ final case class FocusedRef[F[_]: Functor, A, B](ref: Ref[F, A], focus: Contains
focus.set(a, next) -> res
}

def get: F[B] = ref.get.map(focus.extract)
def set(b: B): F[Unit] = ref.update(a => focus.set(a, b))
def get: F[B] = ref.get.map(focus.extract)
def set(b: B): F[Unit] = ref.update(a => focus.set(a, b))

def update(f: B => B): F[Unit] = ref.update(focus.update(_, f))
def modify[X](f: B => (B, X)): F[X] = ref.modify(focusedMod(f))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,10 +108,6 @@ object Logging {
def combine(x: Logging[F], y: Logging[F]): Logging[F] = Logging.combine(x, y)
}

implicit val loggingEmbed: Embed[Logging] = new Embed[Logging] {
def embed[F[_]: FlatMap](ft: F[Logging[F]]): Logging[F] = new EmbedLogging[F](ft)
}

/** log level enumeration */
sealed trait Level

Expand Down
60 changes: 54 additions & 6 deletions logging/structured/src/main/scala/tofu/logging/Logs.scala
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
package tofu.logging

import Logging.loggerForService
import cats.data.Tuple2K
import cats.effect.Sync
import cats.kernel.Monoid
import cats.{Applicative, Apply, FlatMap, Functor}
import cats.tagless.{ApplyK, FunctorK}
import cats.tagless.syntax.functorK._
import cats.{Applicative, Apply, FlatMap, Functor, ~>}
import impl.{ContextSyncLoggingImpl, SyncLogging}
import org.slf4j.LoggerFactory
import tofu.higherKind
import tofu.higherKind.RepresentableK
import tofu.higherKind.{Function2K, MonoidalK, Point, RepresentableK}
import tofu.syntax.monadic._
import tofu.syntax.monoidalK._

import scala.reflect.ClassTag

Expand All @@ -21,14 +25,17 @@ trait Logs[+I[_], F[_]] extends LogsVOps[I, F] {
final def service[Svc: ClassTag]: I[ServiceLogging[F, Svc]] = forService[Svc].asInstanceOf[I[ServiceLogging[F, Svc]]]
}

object Logs {
object Logs extends LogsInstances0 {
def apply[I[_], F[_]](implicit logs: Logs[I, F]): Logs[I, F] = logs

private[this] val logsRepresentableAny: RepresentableK[Logs[*[_], Any]] =
private[this] val logs1RepresentableAny: RepresentableK[Logs[*[_], Any]] =
higherKind.derived.genRepresentableK[Logs[*[_], Any]]

implicit def logsRepresentable[Y[_]]: RepresentableK[Logs[*[_], Y]] =
logsRepresentableAny.asInstanceOf[RepresentableK[Logs[*[_], Y]]]
implicit def logs1Representable[Y[_]]: RepresentableK[Logs[*[_], Y]] =
logs1RepresentableAny.asInstanceOf[RepresentableK[Logs[*[_], Y]]]

implicit def logs2MonoidalK[Y[_]](implicit Y: Applicative[Y]): MonoidalK[Logs[Y, *[_]]] =
new Logs2MonoidalK[Y] { def I: Applicative[Y] = Y }

def provide[I[_], F[_]] = new Provide[I, F]
def provideM[I[_], F[_]] = new ProvideM[I, F]
Expand Down Expand Up @@ -73,3 +80,44 @@ object Logs {
logs.forService[X].flatMap(f)
}
}

private[logging] trait LogsInstances0 extends LogsInstances1 {
implicit def logs2ApplyK[Y[_]](implicit Y: Apply[Y]): ApplyK[Logs[Y, *[_]]] =
new Logs2ApplyK[Y] { def I: Apply[Y] = Y }
}

private[logging] trait LogsInstances1 {
implicit def logs2FunctorK[Y[_]](implicit Y: Functor[Y]): FunctorK[Logs[Y, *[_]]] =
new Logs2FunctorK[Y] { def I: Functor[Y] = Y }
}

trait Logs2FunctorK[Y[_]] extends FunctorK[Logs[Y, *[_]]] {
implicit def I: Functor[Y]

def mapK[F[_], G[_]](af: Logs[Y, F])(fk: F ~> G): Logs[Y, G] = new Logs[Y, G] {
def forService[Svc: ClassTag]: Y[Logging[G]] = af.forService[Svc].map(_.mapK(fk))
def byName(name: String): Y[Logging[G]] = af.byName(name).map(_.mapK(fk))
}
}

trait Logs2ApplyK[Y[_]] extends Logs2FunctorK[Y] with ApplyK[Logs[Y, *[_]]] {
Odomontois marked this conversation as resolved.
Show resolved Hide resolved
implicit def I: Apply[Y]

def zipWith2K[F[_], G[_], H[_]](af: Logs[Y, F], ag: Logs[Y, G])(f2: Function2K[F, G, H]): Logs[Y, H] =
new Logs[Y, H] {
def forService[Svc: ClassTag]: Y[Logging[H]] = (af.forService[Svc], ag.forService[Svc]).mapN(_.zipWithK(_)(f2))
def byName(name: String): Y[Logging[H]] = (af.byName(name), ag.byName(name)).mapN(_.zipWithK(_)(f2))
}

def productK[F[_], G[_]](af: Logs[Y, F], ag: Logs[Y, G]): Logs[Y, Tuple2K[F, G, *]] =
zipWith2K(af, ag)(Function2K((f, g) => Tuple2K(f, g)))
}

trait Logs2MonoidalK[Y[_]] extends Logs2ApplyK[Y] with MonoidalK[Logs[Y, *[_]]] {
implicit def I: Applicative[Y]

def pureK[F[_]](p: Point[F]): Logs[Y, F] = new Logs[Y, F] {
def forService[Svc: ClassTag]: Y[Logging[F]] = p.pureK[Logging].pure[Y]
def byName(name: String): Y[Logging[F]] = p.pureK[Logging].pure[Y]
}
}