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

scalaz.Traverse1.scala Maven / Gradle / Ivy

The newest version!
package scalaz

////
import scalaz.Id.Id

/**
 * A [[scalaz.Traverse]] where `traverse` is total over
 * [[scalaz.Apply]]s.  That is, `toList` cannot return an empty list.
 */
////
trait Traverse1[F[_]] extends Traverse[F] with Foldable1[F] { self =>
  ////

  /**The product of Traverse1 `F` and `G`, `[x](F[x], G[x]])`, is a Traverse1 */
  def product[G[_]](implicit G0: Traverse1[G]): Traverse1[λ[α => (F[α], G[α])]] =
    new ProductTraverse1[F, G] {
      override def F = self
      override def G = G0
    }

  /**The product of Traverse1 `F` and Traverse `G`, `[x](F[x], G[x]])`, is a Traverse1 */
  def product0[G[_]](implicit G0: Traverse[G]): Traverse1[λ[α => (F[α], G[α])]] =
    new ProductTraverse1L[F, G] {
      def F = self
      def G = G0
    }

  /**The composition of Traverse1 `F` and `G`, `[x]F[G[x]]`, is a Traverse1 */
  def compose[G[_]: Traverse1]: Traverse1[λ[α => F[G[α]]]] =
    new CompositionTraverse1[F, G] {
      def F = self
      def G = implicitly
    }

  /** Transform `fa` using `f`, collecting all the `G`s with `ap`. */
  def traverse1Impl[G[_]:Apply,A,B](fa: F[A])(f: A => G[B]): G[F[B]]

  // derived functions
  override def traverseImpl[G[_]:Applicative,A,B](fa: F[A])(f: A => G[B]): G[F[B]] =
    traverse1Impl(fa)(f)

  override def foldMap1[A,B](fa: F[A])(f: A => B)(implicit F: Semigroup[B]): B =
    foldLeft1(traverse1Impl[Id, A, B](fa)(f))(F.append(_, _))

  def traverse1[G[_], A, B](fa: F[A])(f: A => G[B])(implicit a: Apply[G]): G[F[B]] =
    traverse1Impl(fa)(f)

  /** A version of `traverse1` where a subsequent monadic join is applied to the inner result. */
  def traverse1M[A, G[_], B](fa: F[A])(f: A => G[F[B]])(implicit G: Apply[G], F: Bind[F]): G[F[B]] =
    G.map(G.traverse1(fa)(f)(this))(F.join)

  final def traverse1U[A, GB](fa: F[A])(f: A => GB)(implicit G: Unapply[Apply, GB]): G.M[F[G.A]] =
    traverse1(fa)(G.leibniz.onF(f))(G.TC)

  def sequence1[G[_]:Apply,A](fga: F[G[A]]): G[F[A]] =
    traverse1Impl[G, G[A], A](fga)(identity)

  /** A version of `sequence1` where a subsequent monadic join is applied to the inner result */
  def sequence1M[A, G[_]](fgfa: F[G[F[A]]])(implicit G: Apply[G], F: Bind[F]): G[F[A]] =
    G.map(sequence1(fgfa))(F.join)

  final def sequence1U[GA](fga: F[GA])(implicit G: Unapply[Apply, GA]): G.M[F[G.A]] =
    sequence1(G.leibniz.subst(fga))(using G.TC)

  trait Traverse1Law extends TraverseLaw {
    /** Traversal through the [[scalaz.Id]] effect is equivalent to
      * `Functor#map`.
      */
    def identityTraverse1[A, B](fa: F[A], f: A => B)(implicit FB: Equal[F[B]]): Boolean = {
      FB.equal(traverse1[Id, A, B](fa)(f), map(fa)(f))
    }

    /** Two sequentially dependent effects can be fused into one,
      * their composition.
      */
    def sequentialFusion1[N[_], M[_], A, B, C](fa: F[A], amb: A => M[B], bnc: B => N[C])
                                               (implicit N: Apply[N], M: Apply[M], MN: Equal[M[N[F[C]]]]): Boolean = {
      type MN[A] = M[N[A]]
      val t1: MN[F[C]] = M.map(traverse1[M, A, B](fa)(amb))(fb => traverse1[N, B, C](fb)(bnc))
      val t2: MN[F[C]] = traverse1[MN, A, C](fa)(a => M.map(amb(a))(bnc))(M compose N)
      MN.equal(t1, t2)
    }

    /**
     * `naturality` specialized to `sequence1`.
     */
    def naturality1[N[_], M[_], A](nat: (M ~> N))
                                 (fma: F[M[A]])
                                 (implicit N: Apply[N], M: Apply[M], NFA: Equal[N[F[A]]]): Boolean = {
      val n1: N[F[A]] = nat[F[A]](sequence1[M, A](fma))
      val n2: N[F[A]] = sequence1[N, A](map(fma)(ma => nat(ma)))
      NFA.equal(n1, n2)
    }

    /** Two independent effects can be fused into a single effect, their product. */
    def parallelFusion1[N[_], M[_], A, B](fa: F[A], amb: A => M[B], anb: A => N[B])
                                        (implicit N: Apply[N], M: Apply[M], MN: Equal[(M[F[B]], N[F[B]])]): Boolean = {
      type MN[A] = (M[A], N[A])
      val t1: MN[F[B]] = (traverse1[M, A, B](fa)(amb), traverse1[N, A, B](fa)(anb))
      val t2: MN[F[B]] = traverse1[MN, A, B](fa)(a => (amb(a), anb(a)))(M product N)
      MN.equal(t1, t2)
    }
  }
  def traverse1Law: Traverse1Law = new Traverse1Law {}

  ////
  val traverse1Syntax: scalaz.syntax.Traverse1Syntax[F] =
    new scalaz.syntax.Traverse1Syntax[F] { def F = Traverse1.this }
}

object Traverse1 {
  @inline def apply[F[_]](implicit F: Traverse1[F]): Traverse1[F] = F

  import Isomorphism._

  def fromIso[F[_], G[_]](D: F <~> G)(implicit E: Traverse1[G]): Traverse1[F] =
    new IsomorphismTraverse1[F, G] {
      override def G: Traverse1[G] = E
      override def iso: F <~> G = D
    }

  ////

  implicit def idInstance: Traverse1[Id] = Id.id

  ////
}

trait IsomorphismTraverse1[F[_], G[_]] extends Traverse1[F] with IsomorphismTraverse[F, G] with IsomorphismFoldable1[F, G]{
  implicit def G: Traverse1[G]
  ////

  override def traverse1Impl[H[_]: Apply, A, B](fa: F[A])(f: A => H[B]): H[F[B]] =
    Apply[H].map(G.traverse1Impl(iso.to(fa))(f))(iso.from.apply)
  ////
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy