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

logging - scala3 support #1225

Merged
merged 9 commits into from
Apr 17, 2024
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
37 changes: 22 additions & 15 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import complete.DefaultParsers._
import sbt.librarymanagement.CrossVersion.{binaryScalaVersion, partialVersion}

lazy val scala2Versions = List(Version.scala212, Version.scala213)
lazy val scala2And3Versions = scala2Versions ::: List(Version.scala3)
lazy val scala2And3Versions = scala2Versions ++ List(Version.scala3)

val scopesDescription = s"Scala version can be: ${scala2And3Versions.mkString}"
val testScoped = inputKey[Unit](s"Run tests in the given scope. Usage: testScoped [scala version]. $scopesDescription")
Expand Down Expand Up @@ -58,12 +58,13 @@ lazy val higherKindCore = projectMatrix
defaultSettings,
scala3MigratedModuleOptions,
name := "tofu-core-higher-kind",
libraryDependencies ++= Seq(catsCore, catsFree, catsTaglessCore),
libraryDependencies ++= {
CrossVersion.partialVersion(scalaVersion.value) match {
case Some((2, n)) =>
Seq(catsCore, catsFree, catsTaglessMacros)
Seq(catsTaglessMacros)
case _ =>
Seq(catsCore, catsFree, catsTaglessCore)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

seems like module cats-tagless-macros remaines only for Scala 2. Macros for Scala 3 have become available in the cats-tagless-core module since version 0.16.
Sounds like it is time to start working on HigherKindedMacros 😅🔫

Copy link
Contributor

@pomadchin pomadchin Apr 10, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's right! We need to start working on HKT Macro.

All works except type members in the interfaces 🙁

Seq.empty
}
},
)
Expand Down Expand Up @@ -128,30 +129,37 @@ lazy val loggingStr = projectMatrix
.settings(
name := "tofu-logging-structured",
defaultSettings,
scala3MigratedModuleOptions,
libraryDependencies ++= Seq(
catsCore,
circeCore,
tethys,
tethysJackson,
slf4j,
alleycats,
scalatest,
derevo,
catsTaglessMacros
),
catsTaglessCore,
scalatest
)
)
.jvmPlatform(scala2Versions)
.jvmPlatform(scala2And3Versions)
.dependsOn(kernel)

lazy val loggingDer = projectMatrix
.in(modules / "logging" / "derivation")
.settings(
defaultSettings,
libraryDependencies ++= Seq(derevo, magnolia, slf4j, glassMacro % Test),
scala3MigratedModuleOptions,
libraryDependencies ++= {
CrossVersion.partialVersion(scalaVersion.value) match {
case Some((2, _)) => Seq(derevo, magnolia2, slf4j, glassMacro % Test)
case Some((3, _)) => Seq(magnolia3, slf4j)
case _ => Seq.empty
}
},
name := "tofu-logging-derivation"
)
.jvmPlatform(scala2Versions)
.dependsOn(loggingStr, derivation % "compile->test")
.jvmPlatform(scala2And3Versions)
.dependsOn(loggingStr)

lazy val loggingLayout = projectMatrix
.in(modules / "logging" / "layout")
Expand Down Expand Up @@ -270,7 +278,7 @@ lazy val config = projectMatrix
.in(util / "config")
.settings(
defaultSettings,
libraryDependencies ++= Seq(typesafeConfig, magnolia, derevo, glassCore),
libraryDependencies ++= Seq(typesafeConfig, magnolia2, derevo, glassCore),
name := "tofu-config",
)
.jvmPlatform(scala2Versions)
Expand All @@ -290,7 +298,7 @@ lazy val derivation = projectMatrix
.in(modules / "derivation")
.settings(
defaultSettings,
libraryDependencies ++= Seq(magnolia, derevo, catsTaglessMacros),
libraryDependencies ++= Seq(magnolia2, derevo, catsTaglessMacros),
name := "tofu-derivation",
)
.jvmPlatform(scala2Versions)
Expand Down Expand Up @@ -539,8 +547,7 @@ lazy val scala3MigratedModuleOptions =
tpolecatScalacOptions ++= Set(
ScalacOption("-Ykind-projector:underscores", _ >= ScalaVersion.V3_0_0),
ScalacOption("-P:kind-projector:underscore-placeholders", _ < ScalaVersion.V3_0_0),
ScalacOptions.source3,
ScalacOption("-Xmigration", _ < ScalaVersion.V3_0_0)
ScalacOptions.source3
)
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package tofu.common.derived

import cats.Eval
import derevo.Derivation
import magnolia.{CaseClass, Magnolia, SealedTrait}
import magnolia1.{CaseClass, Magnolia, SealedTrait}
import tofu.common.Display

/** Derivation of [[Display]] typeclass for case classes and sealed traits
Expand All @@ -15,7 +15,7 @@ object display extends Derivation[Display] {

private type Typeclass[T] = Display[T]

def combine[T](ctx: CaseClass[Typeclass, T]): Display[T] = (cfg: Display.Config, a: T) => {
def join[T](ctx: CaseClass[Typeclass, T]): Display[T] = (cfg: Display.Config, a: T) => {
import cfg.{fieldSeparator, indent, brackets, fieldAssign, newline}

val nestedIndent = indent + indent
Expand Down Expand Up @@ -57,8 +57,8 @@ object display extends Derivation[Display] {
}
.map(s => s :+ brackets.right)
}
def dispatch[T](ctx: SealedTrait[Typeclass, T]): Display[T] = (cfg: Display.Config, a: T) =>
ctx.dispatch(a)(adtCase => adtCase.typeclass.displayBuild(cfg, adtCase.cast(a)))
def split[T](ctx: SealedTrait[Typeclass, T]): Display[T] = (cfg: Display.Config, a: T) =>
ctx.split(a)(adtCase => adtCase.typeclass.displayBuild(cfg, adtCase.cast(a)))

def instance[T]: Display[T] = macro Magnolia.gen[T]

Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
package tofu.data.derived
import cats.Monad
import derevo.Derivation
import magnolia.{CaseClass, Magnolia}
import mercator.Monadic
import magnolia1.{CaseClass, Magnolia}
import magnolia1.Monadic
import tofu.Init

class InitDerivation[F[_]: Monad] extends Derivation[Init[F, *]] {
private[this] implicit val magnoliaMonad: Monadic[F] = new MerkatorFromCats[F]
private[this] implicit val magnolia1Monad: Monadic[F] = new MerkatorFromCats[F]

type Typeclass[A] = Init[F, A]

def combine[X](cc: CaseClass[Typeclass, X]): Init[F, X] =
def join[X](cc: CaseClass[Typeclass, X]): Init[F, X] =
new Init[F, X] {
def init: F[X] = cc.constructMonadic[F, Any](_.typeclass.init.asInstanceOf[F[Any]])
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package derived

import java.time.{Instant, LocalDate, LocalDateTime, ZonedDateTime}
import cats.kernel.Semigroup
import magnolia.{CaseClass, Magnolia, SealedTrait}
import magnolia1.{CaseClass, Magnolia, SealedTrait}
import derevo.Derivation
import tofu.compat.unused

Expand All @@ -16,11 +16,11 @@ trait Merge[A] {
trait MergeInstances1 {
type Typeclass[A] = Merge[A]

def combine[T](caseClass: CaseClass[Typeclass, T]): Typeclass[T] =
def join[T](caseClass: CaseClass[Typeclass, T]): Typeclass[T] =
(a, b) => caseClass.construct(p => p.typeclass.merge(p.dereference(a), p.dereference(b)))

def dispatch[T](sealedTrait: SealedTrait[Typeclass, T]): Typeclass[T] =
(a, b) => sealedTrait.dispatch(a) { h => if (h.cast.isDefinedAt(b)) h.typeclass.merge(h.cast(a), h.cast(b)) else a }
def split[T](sealedTrait: SealedTrait[Typeclass, T]): Typeclass[T] =
(a, b) => sealedTrait.split(a) { h => if (h.cast.isDefinedAt(b)) h.typeclass.merge(h.cast(a), h.cast(b)) else a }

implicit def instance[A]: Merge[A] = macro Magnolia.gen[A]
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package tofu.data.derived
import cats.Monad
import mercator.Monadic
import magnolia1.Monadic

class MerkatorFromCats[F[_]](implicit F: Monad[F]) extends Monadic[F] {
def point[A](value: A): F[A] = F.pure(value)
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ trait BindInstanceChain[TC[f[_, _]] >: Bind[f]] {

override def handle[E, X, A](fa: Either[E, A], h: E => A): Either[X, A] = Right(fa.fold(h, identity))

override def monad[E]: Monad[Either[E, *]] = implicitly
override def monad[E]: Monad[Either[E, _]] = implicitly

override def bifunctor: Bifunctor[Either] = implicitly
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@ trait Function2K[F[_], G[_], H[_]] {
}

object Function2K {
type HKAny[A] = Any

private[this] val representableAny = new Function2KRepresentable[HKAny, HKAny]

implicit def representableK[F[_], G[_]]: RepresentableK[({ type L[x[_]] = Function2K[F, G, x] })#L] =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,13 @@ import tofu.internal.EffectCompHK
trait MonoidalK[U[_[_]]] extends PureK[U] with ApplyK[U] {
def zipWith2K[F[_], G[_], H[_]](af: U[F], ag: U[G])(f2: Function2K[F, G, H]): U[H]

override def map2K[F[_], G[_], H[_]](af: U[F], ag: U[G])(f: Tuple2K[F, G, *] ~> H): U[H] =
override def map2K[F[_], G[_], H[_]](af: U[F], ag: U[G])(f: Tuple2K[F, G, _] ~> H): U[H] =
zipWith2K(af, ag)(Function2K.untupled(f))

override def mapK[F[_], G[_]](af: U[F])(fk: F ~> G): U[G] =
zipWith2K[F, UnitK, G](af, unitK)(Function2K[F, UnitK]((f, _) => fk(f)))

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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import cats.{Applicative, Apply, FlatMap, Monoid, MonoidK, Semigroup, SemigroupK
import tofu.syntax.funk.funK
import tofu.syntax.monadic.*

/** A function `[F[_], A] =>> A => F[Unit]` An algebra `U[Post[F, *]]` is an algebra which translates all actions to `A
/** A function `[F[_], A] =>> A => F[Unit]` An algebra `U[Post[F, _]]` is an algebra which translates all actions to `A
* \=> F[Unit]`. This is useful to represent actions succeeding main logic.
*/
trait Post[F[_], A] {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import cats.{Applicative, Apply, Monoid, MonoidK, Semigroup, SemigroupK, ~>}
import tofu.syntax.funk.funK
import tofu.syntax.monadic.*

/** Newtype for `[F[_], A] =>> F[Unit]`. An algebra `U[Pre[F, *]]` is an algebra which translates all actions to
/** Newtype for `[F[_], A] =>> F[Unit]`. An algebra `U[Pre[F, _]]` is an algebra which translates all actions to
* `F[Unit]`. This is useful to represent actions preceding main logic.
*/
object Pre extends PreInstances {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import tofu.control.Bind
import tofu.higherKind.bi.RepresentableB.Tab

trait RepresentableB[U[f[_, _]]] extends MonoidalBK[U] with EmbedBK[U] {
def bitabulate[F[_, _]](repr: RepBK[U, *, *] FunBK F): U[F]
def bitabulate[F[_, _]](repr: RepBK[U, _, _] FunBK F): U[F]

final def tab[F[_, _]]: Tab[U, F] = new Tab(this)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,6 @@ package object higherKind {
type Pre[F[_], A] = Pre.T[F, A]

type UnitK[A] = Unit

type HKAny[_] = Any
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ import tofu.instances.bind._

class CatsInstancesFromBindSuite {
def summonBindInstances[F[+_, +_]](implicit bind: Bind[F]): Unit = {
requireApplicative[F[Throwable, *]]
requireFlatMap[F[Nothing, *]]
requireApplicative[F[Throwable, _]]
requireFlatMap[F[Nothing, _]]
}

def requireApplicative[F[_]](implicit applicative: Applicative[F]): Unit = ()
Expand Down
6 changes: 2 additions & 4 deletions modules/kernel/src/main/scala-2/tofu/internal/Interop.scala
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
package tofu.internal
import scala.collection

import scala.reflect.macros._

class Interop(val c: blackbox.Context) {
Expand All @@ -10,9 +10,7 @@ class Interop(val c: blackbox.Context) {
protected def tc[F[_]](implicit wttu: WTTU[F]) = wttu.tpe.typeConstructor
protected def t[A](implicit wttu: WTT[A]) = wttu.tpe

protected def delegateParamTree[N](
ps: collection.Seq[collection.Seq[Tree]]
)(ts: collection.Seq[Type])(implicit N: WTT[N]): Tree = {
protected def delegateParamTree[N](ps: Seq[Seq[Tree]])(ts: Seq[Type])(implicit N: WTT[N]): Tree = {
val s = N.tpe.decls.head.asTerm.name.decodedName.toString
val exp = c.parse(s)

Expand Down
12 changes: 6 additions & 6 deletions modules/kernel/src/main/scala/tofu/Context.scala
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ object Local {
* that can use `F[Ctx]` inside.
*
* @tparam F
* context-aware effect e.g.`ReaderT[Lower, Ctx, *]`
* context-aware effect e.g.`ReaderT[Lower, Ctx, _]`
*/
@deprecated("Migrate to With* typeclasses", "0.10.3")
trait Provide[F[_]] extends ContextBase {
Expand Down Expand Up @@ -205,10 +205,10 @@ trait Provide[F[_]] extends ContextBase {
*
* @example
* {{{ trait ProcessHandler[G[_]] { def mapK[M[_]](fk: G ~> M): ProcessHandler[M] = ??? //...other methods } type
* WithMyContext[F[_], A] = ReaderT[F, MyCtx, A] val contextualProcessHandler: ProcessHandler[IO WithMyContext *] =
* WithMyContext[F[_], A] = ReaderT[F, MyCtx, A] val contextualProcessHandler: ProcessHandler[IO WithMyContext _] =
* ???
*
* val processHandler: ProcessHandler[IO] = processHandler.mapK( WithProvide[IO WithMyContext *, IO,
* val processHandler: ProcessHandler[IO] = processHandler.mapK( WithProvide[IO WithMyContext _, IO,
* MyCtx].runContextK ) }}}
*/
def runContextK(ctx: Ctx): F ~> Lower = funK[F, Lower](a => runContext(a)(ctx))
Expand Down Expand Up @@ -244,7 +244,7 @@ object Provide {
/** Combination of [[Local]] and [[Provide]]
*
* @tparam F
* context-aware effect e.g.`ReaderT[Lower, Ctx, *]`
* context-aware effect e.g.`ReaderT[Lower, Ctx, _]`
*/
@deprecated("Migrate to With* typeclasses", "0.10.3")
trait RunContext[F[_]] extends Local[F] with Provide[F] {
Expand All @@ -256,9 +256,9 @@ trait RunContext[F[_]] extends Local[F] with Provide[F] {
*
* type WithMyContext[F[_], A] = ReaderT[F, MyCtx, A]
*
* val processHandler: ProcessHandler[IO WithMyContext *] = ???
* val processHandler: ProcessHandler[IO WithMyContext _] = ???
*
* val contextualHandler: IO WithMyContext ProcessHandler[IO] = processHandler.mapK( WithRun[WithMyContext[IO, *],
* val contextualHandler: IO WithMyContext ProcessHandler[IO] = processHandler.mapK( WithRun[WithMyContext[IO, _],
* IO, MyCtx].unlift.map(fk => processHandler.mapK(fk)) ) //now it is able to process MyCtx but is wrapped in IO
* WithMyContext * }}}
* @return
Expand Down
10 changes: 5 additions & 5 deletions modules/kernel/src/main/scala/tofu/Errors.scala
Original file line number Diff line number Diff line change
Expand Up @@ -130,8 +130,8 @@ object Errors extends DataEffectComp[Errors] {
trait ErrorBase
object ErrorBase extends ErrorsBaseInstances {

final implicit def readerTErrors[F[_], R, E](implicit F: Errors[F, E]): Errors[ReaderT[F, R, *], E] =
new Errors[ReaderT[F, R, *], E] {
final implicit def readerTErrors[F[_], R, E](implicit F: Errors[F, E]): Errors[ReaderT[F, R, _], E] =
new Errors[ReaderT[F, R, _], E] {
def raise[A](err: E): ReaderT[F, R, A] =
ReaderT.liftF(F.raise(err))

Expand Down Expand Up @@ -177,12 +177,12 @@ class ErrorsBaseInstances2 extends ErrorsBaseInstances3 {

class ErrorsBaseInstances3 {

final implicit def eitherTIntance[F[_], E](implicit F: Monad[F]): ErrorsTo[EitherT[F, E, *], F, E] =
final implicit def eitherTIntance[F[_], E](implicit F: Monad[F]): ErrorsTo[EitherT[F, E, _], F, E] =
new EitherTErrorsTo[F, E]

final implicit def optionTIntance[F[_]](implicit F: Monad[F]): ErrorsTo[OptionT[F, *], F, Unit] =
final implicit def optionTIntance[F[_]](implicit F: Monad[F]): ErrorsTo[OptionT[F, _], F, Unit] =
new OptionTErrorsTo[F]

final implicit def eitherIntance[E]: ErrorsTo[Either[E, *], Id, E] = new EitherErrorsTo[E]
final implicit def eitherIntance[E]: ErrorsTo[Either[E, _], Id, E] = new EitherErrorsTo[E]
final implicit val optionTIntance: ErrorsTo[Option, Id, Unit] = OptionErrorsTo
}
4 changes: 2 additions & 2 deletions modules/kernel/src/main/scala/tofu/Perform.scala
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ trait Performer[F[_], -Cont[_], Cancel] {
}

object Performer {
type OfExit[F[_], E] = Performer[F, PerformOf.ExitCont[E, *], Unit]
type OfExit[F[_], E] = Performer[F, PerformOf.ExitCont[E, _], Unit]

implicit def contravariantK[F[_], Cancel]: ContravariantK[({ type L[x[_]] = Performer[F, x, Cancel] })#L] =
new PerformerContravariantK[F, Cancel]
Expand All @@ -49,7 +49,7 @@ object PerformVia extends PerformInstance with PerformInstance1 {
trait PerformInstance1 {
implicit def performReader[F[_]: Functor, Cont[_], R, Cancel](implicit
RP: PerformVia[F, Cont, Cancel]
): PerformVia[ReaderT[F, R, *], Cont, Cancel] = new PerformViaReader(RP)
): PerformVia[ReaderT[F, R, _], Cont, Cancel] = new PerformViaReader(RP)
}

object PerformOf extends Effect2Comp[PerformOf] {
Expand Down
4 changes: 2 additions & 2 deletions modules/kernel/src/main/scala/tofu/Scoped.scala
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ trait Scoped[Tag, F[_]] {

final def tagged[NewTag]: Scoped[NewTag, F] = this.asInstanceOf[Scoped[NewTag, F]]

final def midPoint: Point[Mid[F, *]] = new Point[Mid[F, *]] {
final def midPoint: Point[Mid[F, _]] = new Point[Mid[F, _]] {
def point[A]: Mid[F, A] = runScoped(_)
}
}
Expand Down Expand Up @@ -78,7 +78,7 @@ object Scoped extends ScopedInstance with ScopedInstancesMacro {
}

/** helpful method to create middleware that executes all proceses in the given scope */
def mid[Tag, U[_[_]], F[_]](implicit U: PureK[U], F: Scoped[Tag, F]): U[Mid[F, *]] = U.pureK(F.midPoint)
def mid[Tag, U[_[_]], F[_]](implicit U: PureK[U], F: Scoped[Tag, F]): U[Mid[F, _]] = U.pureK(F.midPoint)
}

trait ScopedExecute[Tag, F[_]] extends Scoped[Tag, F] {
Expand Down
Loading
Loading