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

emm.effects.Mapper.scala Maven / Gradle / Ivy

The newest version!
package emm
package effects

import shims.{Applicative, FlatMap, Functor, Monad, Traverse}
import scala.annotation.implicitNotFound

import properties._

@implicitNotFound("could not compute a method for mapping over effect stack ${C}; either a member of the stack lacks an Applicative, or its Applicative instance is ambiguous")
trait Mapper[C <: Effects] { outer =>
  type CC[A] = C#Point[A]

  def point[A](a: A): CC[A]

  def map[A, B](fa: CC[A])(f: A => B): CC[B]

  def functor: Functor[CC] = new Functor[CC] {
    def map[A, B](fa: CC[A])(f: A => B): CC[B] = outer.map(fa)(f)
  }
}

object Mapper {

  implicit def base: Mapper[Base] = new Mapper[Base] {
    def point[A](a: A) = a
    def map[A, B](fa: A)(f: A => B) = f(fa)
  }

  implicit def corecurse1[F[_], C <: Effects](implicit P: Mapper[C], NN: NonNested[C], F: Applicative[F]): Mapper[F |: C] = new Mapper[F |: C] {

    def point[A](a: A) = NN.pack(F.point(P.point(a)))

    def map[A, B](fa: CC[A])(f: A => B): CC[B] =
      NN.pack(F.map(NN.unpack(fa)) { ca => P.map(ca)(f) })
  }

  implicit def corecurse2[F[_, _], F2[_, _], Z, C <: Effects](implicit ev: Permute2[F, F2], P: Mapper[C], NN: NonNested[C], F: Applicative[F2[Z, ?]]): Mapper[F2[Z, ?] |: C] = corecurse1[F2[Z, ?], C]
  implicit def corecurse3[F[_, _, _], F2[_, _, _], Y, Z, C <: Effects](implicit ev: Permute3[F, F2], P: Mapper[C], NN: NonNested[C], F: Applicative[F2[Y, Z, ?]]): Mapper[F2[Y, Z, ?] |: C] = corecurse1[F2[Y, Z, ?], C]

  implicit def corecurseH1[F[_[_], _], G[_], C <: Effects](implicit P: Mapper[C], NN: NonNested[C], F: Applicative[F[G, ?]]): Mapper[F[G, ?] |: C] = corecurse1[F[G, ?], C]
  implicit def corecurseH2[F[_[_], _, _], F2[_[_], _, _], G[_], Z, C <: Effects](implicit ev: PermuteH2[F, F2], P: Mapper[C], NN: NonNested[C], F: Applicative[F2[G, Z, ?]]): Mapper[F2[G, Z, ?] |: C] = corecurse1[F2[G, Z, ?], C]
  implicit def corecurseH3[F[_[_], _, _, _], F2[_[_], _, _, _], G[_], Y, Z, C <: Effects](implicit ev: PermuteH3[F, F2], P: Mapper[C], NN: NonNested[C], F: Applicative[F2[G, Y, Z, ?]]): Mapper[F2[G, Y, Z, ?] |: C] = corecurse1[F2[G, Y, Z, ?], C]

  implicit def pivot1[Pivot[_[_], _], C <: Effects, F <: Effects, T <: Effects](implicit NAP: NestedAtPoint[C, Pivot, F, T], Pivot: Applicative[Pivot[F#Point, ?]], T: Mapper[T]): Mapper[C] = new Mapper[C] {

    def point[A](a: A): CC[A] = NAP.pack(Pivot.point(T.point(a)))

    def map[A, B](fa: CC[A])(f: A => B): CC[B] =
      NAP.pack(Pivot.map(NAP.unpack(fa)) { ta => T.map(ta)(f) })
  }

  implicit def pivot2[Pivot[_[_], _, _], Pivot2[_[_], _, _], Z, C <: Effects, F <: Effects, T <: Effects](implicit NAP: NestedAtPoint[C, Pivot2[?[_], Z, ?], F, T], ev: PermuteH2[Pivot, Pivot2], Pivot: Applicative[Pivot2[F#Point, Z, ?]], T: Mapper[T]): Mapper[C] = pivot1[Pivot2[?[_], Z, ?], C, F, T]
  implicit def pivot3[Pivot[_[_], _, _, _], Pivot2[_[_], _, _, _], Y, Z, C <: Effects, F <: Effects, T <: Effects](implicit NAP: NestedAtPoint[C, Pivot2[?[_], Y, Z, ?], F, T], ev: PermuteH3[Pivot, Pivot2], Pivot: Applicative[Pivot2[F#Point, Y, Z, ?]], T: Mapper[T]): Mapper[C] = pivot1[Pivot2[?[_], Y, Z, ?], C, F, T]
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy