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

scalaz.Traverse.scala Maven / Gradle / Ivy

The newest version!
package scalaz

////
import scalaz.Id.Id

/**
 * Idiomatic traversal of a structure, as described in
 * [[http://www.cs.ox.ac.uk/jeremy.gibbons/publications/iterator.pdf The Essence of the Iterator Pattern]].
 *
 * @see [[scalaz.Traverse.TraverseLaw]]
 */
////
trait Traverse[F[_]] extends Functor[F] with Foldable[F] { self =>
  ////

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

  // derived functions

  /**The composition of Traverses `F` and `G`, `[x]F[G[x]]`, is a Traverse */
  def compose[G[_]](implicit G0: Traverse[G]): Traverse[λ[α => F[G[α]]]] =
    new CompositionTraverse[F, G] {
      override def F = self
      override def G = G0
    }

  /** The composition of Traverse `F` and Bitraverse `G`, `[x, y]F[G[x, y]]`, is a Bitraverse */
  def bicompose[G[_, _]: Bitraverse]: Bitraverse[λ[(α, β) => F[G[α, β]]]] =
    new CompositionTraverseBitraverse[F, G] {
      def F = self
      def G = implicitly
    }

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

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

  class Traversal[G[_]](implicit G: Applicative[G]) {
    def run[A,B](fa: F[A])(f: A => G[B]): G[F[B]] = traverseImpl[G,A,B](fa)(f)
  }

  // reduce - given monoid
  def traversal[G[_]:Applicative]: Traversal[G] =
    new Traversal[G]
  def traversalS[S]: Traversal[State[S, *]] =
    new Traversal[State[S, *]]()(StateT.stateMonad) {
      override def run[A, B](fa: F[A])(f: A => State[S, B]) = traverseS(fa)(f)
    }

  def traverse[G[_]:Applicative,A,B](fa: F[A])(f: A => G[B]): G[F[B]] =
    traversal[G].run(fa)(f)

  /** A version of `traverse` that infers the type constructor `G`. */
  final def traverseU[A, GB](fa: F[A])(f: A => GB)(implicit G: Unapply[Applicative, GB]): G.M[F[G.A]] /*G[F[B]]*/ =
    G.TC.traverse(fa)(G.leibniz.onF(f))(this)

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

  /** Traverse with `State`. */
  def traverseS[S,A,B](fa: F[A])(f: A => State[S,B]): State[S,F[B]] =
    traverseSTrampoline[S, Id.Id, A, B](fa)(f)

  def runTraverseS[S,A,B](fa: F[A], s: S)(f: A => State[S,B]): (S, F[B]) =
    traverseS(fa)(f)(s)

  /** Traverse `fa` with a `State[S, G[B]]`, internally using a `Trampoline` to avoid stack overflow. */
  def traverseSTrampoline[S, G[_] : Applicative, A, B](fa: F[A])(f: A => State[S, G[B]]): State[S, G[F[B]]] = {
    import Free._
    implicit val A: Applicative[({type l[a] = StateT[S, Trampoline, G[a]]})#l] =
      StateT.stateTMonadState[S, Trampoline].compose(Applicative[G])
    State[S, G[F[B]]](s => {
      val st = traverse[λ[α => StateT[S, Trampoline, G[α]]], A, B](fa)(f(_: A).lift[Trampoline])
      st.run(s).run
    })
  }

  /** Traverse `fa` with a `Kleisli[G, S, B]`, internally using a `Trampoline` to avoid stack overflow. */
  def traverseKTrampoline[S, G[_] : Applicative, A, B](fa: F[A])(f: A => Kleisli[G, S, B]): Kleisli[G, S, F[B]] = {
    import Free._
    implicit val A: Applicative[({type l[a] = Kleisli[Trampoline, S, G[a]]})#l] =
      Kleisli.kleisliMonadReader[Trampoline, S].compose(Applicative[G])
    Kleisli[G, S, F[B]](s => {
      val kl = traverse[λ[α => Kleisli[Trampoline, S, G[α]]], A, B](fa)(z => Kleisli[Id, S, G[B]](i => f(z)(i)).lift[Trampoline]).run(s)
      kl.run
    })
  }

  /** Traverse with the identity function. */
  def sequence[G[_]:Applicative,A](fga: F[G[A]]): G[F[A]] =
    traversal[G].run[G[A], A](fga)(ga => ga)

  /** Traverse with `State`. */
  def sequenceS[S,A](fga: F[State[S,A]]): State[S,F[A]] =
    traverseS(fga)(x => x)

  /** A version of `sequence` that infers the nested type constructor. */
  final def sequenceU[A](self: F[A])(implicit G: Unapply[Applicative, A]): G.M[F[G.A]] /*G[F[A]] */ =
    G.TC.traverse(self)(x => G.apply(x))(this)

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

  override def map[A,B](fa: F[A])(f: A => B): F[B] =
    traversal[Id](using Id.id).run(fa)(f)

  def foldLShape[A,B](fa: F[A], z: B)(f: (B,A) => B): (B, F[Unit]) =
    runTraverseS(fa, z)(a => State.modify(f(_, a)))

  override def foldLeft[A,B](fa: F[A], z: B)(f: (B,A) => B): B = foldLShape(fa, z)(f)._1

  def foldMap[A,B](fa: F[A])(f: A => B)(implicit F: Monoid[B]): B = foldLShape(fa, F.zero)((b, a) => F.append(b, f(a)))._1

  override def foldRight[A, B](fa: F[A], z: => B)(f: (A, => B) => B) =
    foldMap(fa)((a: A) => Endo.endoByName[B](f(a, _))) apply z

  def reverse[A](fa: F[A]): F[A] = {
    val (as, shape) = mapAccumL(fa, scala.List[A]())((t,h) => (h :: t,h))
    runTraverseS(shape, as)(_ => for {
      e <- State.get
      _ <- State.put(e.tail)
    } yield e.head)._2
  }

  def zipWith[A,B,C](fa: F[A], fb: F[B])(f: (A, Option[B]) => C): (List[B], F[C]) =
    runTraverseS(fa, toList(fb))(a => for {
      bs <- State.get
      _ <- State.put(if (bs.isEmpty) bs else bs.tail)
    } yield f(a, bs.headOption))

  def zipWithL[A,B,C](fa: F[A], fb: F[B])(f: (A,Option[B]) => C): F[C] = zipWith(fa, fb)(f)._2
  def zipWithR[A,B,C](fa: F[A], fb: F[B])(f: (Option[A],B) => C): F[C] = zipWith(fb, fa)((b,oa) => f(oa,b))._2

  def indexed[A](fa: F[A]): F[(Int, A)] = mapAccumL(fa, 0) { case (s, a) => (s + 1, (s, a)) }._2

  def zipL[A,B](fa: F[A], fb: F[B]): F[(A, Option[B])] = zipWithL(fa, fb)((_,_))
  def zipR[A,B](fa: F[A], fb: F[B]): F[(Option[A], B)] = zipWithR(fa, fb)((_,_))

  def mapAccumL[S,A,B](fa: F[A], z: S)(f: (S,A) => (S,B)): (S, F[B]) =
    runTraverseS(fa, z)(a => for {
      s1 <- State.init[S]
      (s2,b) = f(s1,a)
      _ <- State.put(s2)
    } yield b)

  def mapAccumR[S,A,B](fa: F[A], z: S)(f: (S,A) => (S,B)): (S, F[B]) =
    mapAccumL(reverse(fa), z)(f) match { case (s, fb) => (s, reverse(fb)) }

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

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

    /** Traversal with the `point` function is the same as applying the `point` function directly */
    def purity[G[_], A](fa: F[A])(implicit G: Applicative[G], GFA: Equal[G[F[A]]]): Boolean =
      GFA.equal(traverse[G, A, A](fa)(G.point[A](_)), G.point(fa))

    /**
     * @param nat A natural transformation from `M` to `N` for which these properties hold:
     *            `(a: A) => nat(Applicative[M].point[A](a)) === Applicative[N].point[A](a)`
     *            `(f: M[A => B], ma: M[A]) => nat(Applicative[M].ap(ma)(f)) === Applicative[N].ap(nat(ma))(nat(f))`
     */
    def naturality[N[_], M[_], A](nat: (M ~> N))
                                 (fma: F[M[A]])
                                 (implicit N: Applicative[N], M: Applicative[M], NFA: Equal[N[F[A]]]): Boolean = {
      val n1: N[F[A]] = nat[F[A]](sequence[M, A](fma))
      val n2: N[F[A]] = sequence[N, A](map(fma)(ma => nat(ma)))
      NFA.equal(n1, n2)
    }

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

  ////
  val traverseSyntax: scalaz.syntax.TraverseSyntax[F] =
    new scalaz.syntax.TraverseSyntax[F] { def F = Traverse.this }
}

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

  import Isomorphism._

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

  ////

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

  ////
}

trait IsomorphismTraverse[F[_], G[_]] extends Traverse[F] with IsomorphismFunctor[F, G] with IsomorphismFoldable[F, G]{
  implicit def G: Traverse[G]
  ////

  protected[this] override final def naturalTrans: F ~> G = iso.to

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




© 2015 - 2025 Weber Informatics LLC | Privacy Policy