Skip to content

Instantly share code, notes, and snippets.

@gvolpe
Forked from neko-kai/quantified.scala
Created January 12, 2019 01:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gvolpe/42a0783fb78a44b2c65bad97c89501d6 to your computer and use it in GitHub Desktop.
Save gvolpe/42a0783fb78a44b2c65bad97c89501d6 to your computer and use it in GitHub Desktop.
Tagless final for ZIO via quantified constraints
package quantified
import cats.Monad
import scala.language.implicitConversions
/** C[_] constraint applied to type F[_, _] quantified in first parameter */
final class Quant[+C[_[_]], F[_, _]] private (private val erased: C[F[Any, ?]]) extends AnyVal {
type State = Defined
@inline def underlying[E]: C[F[E, ?]] = erased.asInstanceOf[C[F[E, ?]]]
}
object Quant extends QuantImplicits {
@inline final def apply[C[_[_]], F[_, _]](implicit q: Quant[C, F]): Quant[C, F] = q
final def apply[C[_[_]]]: QuantApply[C] = new QuantApply[C]()
private[Quant] final class QuantApply[C[_[_]]](private val dummy: Boolean = false) extends AnyVal {
def apply[F[_, _], E](c: C[F[E, ?]]): Quant[C, F] = new Quant[C, F](c.asInstanceOf[C[F[Any, ?]]])
}
private sealed trait Private {
private[Quant] type T
}
private[Quant] final val Private = new Private {}
/** If somehow there's an instance that's valid for a fresh private type T >: Nothing <: Any,
it means that this instance must be a polymorphic instance valid for all type parameters X >: Nothing <: Any **/
implicit def fromImplicitDef[C[_[_]], F[_, _]](implicit lp: shapeless.LowPriority, c: C[F[Private.T, ?]]): Quant[C, F] { type State = Derived } =
Quant[C].apply(c.asInstanceOf[C[F[Any, ?]]]).asInstanceOf[Quant[C, F] { type State = Derived }]
}
trait QuantImplicits extends Any {
final type Monad2[F[_, _]] = Quant[Monad, F]
object Monad2 {
final def apply[F[_, _]: Monad2]: Monad2[F] = implicitly[Quant.Monad2[F]]
implicit final class Monad2CovariantFlatMap[F[+_, _], E, A](self: F[E, A])(implicit ev: Monad2[F] { type State = Defined }) {
@inline def flatMap[E1 >: E, B](f: A => F[E1, B]): F[E1, B] =
apply[F].apply[E1].flatMap(self)(f)
@inline def *>[E1 >: E, B](f: => F[E1, B]): F[E1, B] =
flatMap[E1, B](_ => f)
}
}
@inline implicit final def instantiate[C[_[_]], F[_, _], E](implicit lp: shapeless.LowPriority, q: Quant[C, F] { type State = Defined }): C[F[E, ?]] = q.underlying
// Also works via Param:
// @inline implicit final def instantiate[C[_[_]], F[_, _], E](implicit lp: shapeless.LowPriority, c: Param[Lambda[E => C[F[E, ?]]]] { type State = Defined }): C[F[E, ?]] = c.underlying
@inline implicit final def conversion[C[_[_]], F[_, _], E](q: Quant[C, F]): C[F[E, ?]] = q.underlying
}
private[quantified] trait Defined
private[quantified] trait Derived
/** Universally quantified instance for C */
final class Param[C[_]](private val erased: C[_]) {
type State = Defined
def underlying[A]: C[A] = erased.asInstanceOf[C[A]]
}
object Param extends ParamImplicits {
def apply[C[_]: Param]: Param[C] = implicitly
private sealed trait Private {
private[Param] trait T extends Any
}
private[Param] final val Private = new Private {}
/** If there's somehow an instance for a fresh private type >: Nothing <: Any,
it means that this instance is a polymorphic instance valid for all type parameters >: Nothing <: Any **/
implicit def fromImplicitDef[C[_]](implicit lp: shapeless.LowPriority, c: C[Private.T]): Param[C] { type State = Derived } =
new Param(c).asInstanceOf[Param[C] { type State = Derived }]
}
trait ParamImplicits {
@inline implicit final def instantiate[C[_], A](implicit lp: shapeless.LowPriority, c: Param[C] { type State = Defined }): C[A] = c.underlying
@inline implicit final def conversion[C[_], A](c: Param[C]): C[A] = c.underlying
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment