PageRenderTime 38ms CodeModel.GetById 14ms app.highlight 20ms RepoModel.GetById 1ms app.codeStats 0ms

/core/src/main/scala/scalaz/Traverse.scala

http://github.com/scalaz/scalaz
Scala | 233 lines | 147 code | 47 blank | 39 comment | 4 complexity | 4a591e5e027939dcc06f0e6b1fb69c64 MD5 | raw file
  1package scalaz
  2
  3////
  4import scalaz.Id.Id
  5
  6/**
  7 * Idiomatic traversal of a structure, as described in
  8 * [[http://www.cs.ox.ac.uk/jeremy.gibbons/publications/iterator.pdf The Essence of the Iterator Pattern]].
  9 *
 10 * @see [[scalaz.Traverse.TraverseLaw]]
 11 */
 12////
 13trait Traverse[F[_]] extends Functor[F] with Foldable[F] { self =>
 14  ////
 15
 16  /** Transform `fa` using `f`, collecting all the `G`s with `ap`. */
 17  def traverseImpl[G[_]:Applicative,A,B](fa: F[A])(f: A => G[B]): G[F[B]]
 18
 19  // derived functions
 20
 21  /**The composition of Traverses `F` and `G`, `[x]F[G[x]]`, is a Traverse */
 22  def compose[G[_]](implicit G0: Traverse[G]): Traverse[λ[α => F[G[α]]]] =
 23    new CompositionTraverse[F, G] {
 24      implicit def F = self
 25      implicit def G = G0
 26    }
 27
 28  /** The composition of Traverse `F` and Bitraverse `G`, `[x, y]F[G[x, y]]`, is a Bitraverse */
 29  def bicompose[G[_, _]: Bitraverse]: Bitraverse[λ[(α, β) => F[G[α, β]]]] =
 30    new CompositionTraverseBitraverse[F, G] {
 31      def F = self
 32      def G = implicitly
 33    }
 34
 35  /**The product of Traverses `F` and `G`, `[x](F[x], G[x]])`, is a Traverse */
 36  def product[G[_]](implicit G0: Traverse[G]): Traverse[λ[α => (F[α], G[α])]] =
 37    new ProductTraverse[F, G] {
 38      implicit def F = self
 39      implicit def G = G0
 40    }
 41
 42  /**The product of Traverse `F` and Traverse1 `G`, `[x](F[x], G[x]])`, is a Traverse1 */
 43  def product0[G[_]](implicit G0: Traverse1[G]): Traverse1[λ[α => (F[α], G[α])]] =
 44    new ProductTraverse1R[F, G] {
 45      def F = self
 46      def G = G0
 47    }
 48
 49  class Traversal[G[_]](implicit G: Applicative[G]) {
 50    def run[A,B](fa: F[A])(f: A => G[B]): G[F[B]] = traverseImpl[G,A,B](fa)(f)
 51  }
 52
 53  // reduce - given monoid
 54  def traversal[G[_]:Applicative]: Traversal[G] =
 55    new Traversal[G]
 56  def traversalS[S]: Traversal[State[S, *]] =
 57    new Traversal[State[S, *]]()(StateT.stateMonad) {
 58      override def run[A, B](fa: F[A])(f: A => State[S, B]) = traverseS(fa)(f)
 59    }
 60
 61  def traverse[G[_]:Applicative,A,B](fa: F[A])(f: A => G[B]): G[F[B]] =
 62    traversal[G].run(fa)(f)
 63
 64  /** A version of `traverse` that infers the type constructor `G`. */
 65  final def traverseU[A, GB](fa: F[A])(f: A => GB)(implicit G: Unapply[Applicative, GB]): G.M[F[G.A]] /*G[F[B]]*/ =
 66    G.TC.traverse(fa)(G.leibniz.onF(f))(this)
 67
 68  /** A version of `traverse` where a subsequent monadic join is applied to the inner result. */
 69  final def traverseM[A, G[_], B](fa: F[A])(f: A => G[F[B]])(implicit G: Applicative[G], F: Bind[F]): G[F[B]] =
 70    G.map(G.traverse(fa)(f)(this))(F.join)
 71
 72  /** Traverse with `State`. */
 73  def traverseS[S,A,B](fa: F[A])(f: A => State[S,B]): State[S,F[B]] =
 74    traverseSTrampoline[S, Id.Id, A, B](fa)(f)
 75
 76  def runTraverseS[S,A,B](fa: F[A], s: S)(f: A => State[S,B]): (S, F[B]) =
 77    traverseS(fa)(f)(s)
 78
 79  /** Traverse `fa` with a `State[S, G[B]]`, internally using a `Trampoline` to avoid stack overflow. */
 80  def traverseSTrampoline[S, G[_] : Applicative, A, B](fa: F[A])(f: A => State[S, G[B]]): State[S, G[F[B]]] = {
 81    import Free._
 82    implicit val A = StateT.stateTMonadState[S, Trampoline].compose(Applicative[G])
 83    State[S, G[F[B]]](s => {
 84      val st = traverse[λ[α => StateT[S, Trampoline, G[α]]], A, B](fa)(f(_: A).lift[Trampoline])
 85      st.run(s).run
 86    })
 87  }
 88
 89  /** Traverse `fa` with a `Kleisli[G, S, B]`, internally using a `Trampoline` to avoid stack overflow. */
 90  def traverseKTrampoline[S, G[_] : Applicative, A, B](fa: F[A])(f: A => Kleisli[G, S, B]): Kleisli[G, S, F[B]] = {
 91    import Free._
 92    implicit val A = Kleisli.kleisliMonadReader[Trampoline, S].compose(Applicative[G])
 93    Kleisli[G, S, F[B]](s => {
 94      val kl = traverse[λ[α => Kleisli[Trampoline, S, G[α]]], A, B](fa)(z => Kleisli[Id, S, G[B]](i => f(z)(i)).lift[Trampoline]).run(s)
 95      kl.run
 96    })
 97  }
 98
 99  /** Traverse with the identity function. */
100  def sequence[G[_]:Applicative,A](fga: F[G[A]]): G[F[A]] =
101    traversal[G].run[G[A], A](fga)(ga => ga)
102
103  /** Traverse with `State`. */
104  def sequenceS[S,A](fga: F[State[S,A]]): State[S,F[A]] =
105    traverseS(fga)(x => x)
106
107  /** A version of `sequence` that infers the nested type constructor. */
108  final def sequenceU[A](self: F[A])(implicit G: Unapply[Applicative, A]): G.M[F[G.A]] /*G[F[A]] */ =
109    G.TC.traverse(self)(x => G.apply(x))(this)
110
111  /** A version of `sequence` where a subsequent monadic join is applied to the inner result */
112  def sequenceM[A, G[_]](fgfa: F[G[F[A]]])(implicit G: Applicative[G], F: Bind[F]): G[F[A]] =
113    G.map(sequence(fgfa))(F.join)
114
115  override def map[A,B](fa: F[A])(f: A => B): F[B] =
116    traversal[Id](Id.id).run(fa)(f)
117
118  def foldLShape[A,B](fa: F[A], z: B)(f: (B,A) => B): (B, F[Unit]) =
119    runTraverseS(fa, z)(a => State.modify(f(_, a)))
120
121  override def foldLeft[A,B](fa: F[A], z: B)(f: (B,A) => B): B = foldLShape(fa, z)(f)._1
122
123  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
124
125  override def foldRight[A, B](fa: F[A], z: => B)(f: (A, => B) => B) =
126    foldMap(fa)((a: A) => Endo.endoByName[B](f(a, _))) apply z
127
128  def reverse[A](fa: F[A]): F[A] = {
129    val (as, shape) = mapAccumL(fa, scala.List[A]())((t,h) => (h :: t,h))
130    runTraverseS(shape, as)(_ => for {
131      e <- State.get
132      _ <- State.put(e.tail)
133    } yield e.head)._2
134  }
135
136  def zipWith[A,B,C](fa: F[A], fb: F[B])(f: (A, Option[B]) => C): (List[B], F[C]) =
137    runTraverseS(fa, toList(fb))(a => for {
138      bs <- State.get
139      _ <- State.put(if (bs.isEmpty) bs else bs.tail)
140    } yield f(a, bs.headOption))
141
142  def zipWithL[A,B,C](fa: F[A], fb: F[B])(f: (A,Option[B]) => C): F[C] = zipWith(fa, fb)(f)._2
143  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
144
145  def indexed[A](fa: F[A]): F[(Int, A)] = mapAccumL(fa, 0) { case (s, a) => (s + 1, (s, a)) }._2
146
147  def zipL[A,B](fa: F[A], fb: F[B]): F[(A, Option[B])] = zipWithL(fa, fb)((_,_))
148  def zipR[A,B](fa: F[A], fb: F[B]): F[(Option[A], B)] = zipWithR(fa, fb)((_,_))
149
150  def mapAccumL[S,A,B](fa: F[A], z: S)(f: (S,A) => (S,B)): (S, F[B]) =
151    runTraverseS(fa, z)(a => for {
152      s1 <- State.init[S]
153      (s2,b) = f(s1,a)
154      _ <- State.put(s2)
155    } yield b)
156
157  def mapAccumR[S,A,B](fa: F[A], z: S)(f: (S,A) => (S,B)): (S, F[B]) =
158    mapAccumL(reverse(fa), z)(f) match { case (s, fb) => (s, reverse(fb)) }
159
160  trait TraverseLaw extends FunctorLaw {
161    /** Traversal through the [[scalaz.Id]] effect is equivalent to `Functor#map` */
162    def identityTraverse[A, B](fa: F[A], f: A => B)(implicit FB: Equal[F[B]]): Boolean = {
163      FB.equal(traverse[Id, A, B](fa)(f), map(fa)(f))
164    }
165
166    /** Two sequentially dependent effects can be fused into one, their composition */
167    def sequentialFusion[N[_], M[_], A, B, C](fa: F[A], amb: A => M[B], bnc: B => N[C])
168                                               (implicit N: Applicative[N], M: Applicative[M], MN: Equal[M[N[F[C]]]]): Boolean = {
169      type MN[A] = M[N[A]]
170      val t1: MN[F[C]] = M.map(traverse[M, A, B](fa)(amb))(fb => traverse[N, B, C](fb)(bnc))
171      val t2: MN[F[C]] = traverse[MN, A, C](fa)(a => M.map(amb(a))(bnc))(M compose N)
172      MN.equal(t1, t2)
173    }
174
175    /** Traversal with the `point` function is the same as applying the `point` function directly */
176    def purity[G[_], A](fa: F[A])(implicit G: Applicative[G], GFA: Equal[G[F[A]]]): Boolean =
177      GFA.equal(traverse[G, A, A](fa)(G.point[A](_)), G.point(fa))
178
179    /**
180     * @param nat A natural transformation from `M` to `N` for which these properties hold:
181     *            `(a: A) => nat(Applicative[M].point[A](a)) === Applicative[N].point[A](a)`
182     *            `(f: M[A => B], ma: M[A]) => nat(Applicative[M].ap(ma)(f)) === Applicative[N].ap(nat(ma))(nat(f))`
183     */
184    def naturality[N[_], M[_], A](nat: (M ~> N))
185                                 (fma: F[M[A]])
186                                 (implicit N: Applicative[N], M: Applicative[M], NFA: Equal[N[F[A]]]): Boolean = {
187      val n1: N[F[A]] = nat[F[A]](sequence[M, A](fma))
188      val n2: N[F[A]] = sequence[N, A](map(fma)(ma => nat(ma)))
189      NFA.equal(n1, n2)
190    }
191
192    /** Two independent effects can be fused into a single effect, their product. */
193    def parallelFusion[N[_], M[_], A, B](fa: F[A], amb: A => M[B], anb: A => N[B])
194                                        (implicit N: Applicative[N], M: Applicative[M], MN: Equal[(M[F[B]], N[F[B]])]): Boolean = {
195      type MN[A] = (M[A], N[A])
196      val t1: MN[F[B]] = (traverse[M, A, B](fa)(amb), traverse[N, A, B](fa)(anb))
197      val t2: MN[F[B]] = traverse[MN, A, B](fa)(a => (amb(a), anb(a)))(M product N)
198      MN.equal(t1, t2)
199    }
200  }
201  def traverseLaw = new TraverseLaw {}
202
203  ////
204  val traverseSyntax: scalaz.syntax.TraverseSyntax[F] =
205    new scalaz.syntax.TraverseSyntax[F] { def F = Traverse.this }
206}
207
208object Traverse {
209  @inline def apply[F[_]](implicit F: Traverse[F]): Traverse[F] = F
210
211  import Isomorphism._
212
213  def fromIso[F[_], G[_]](D: F <~> G)(implicit E: Traverse[G]): Traverse[F] =
214    new IsomorphismTraverse[F, G] {
215      override def G: Traverse[G] = E
216      override def iso: F <~> G = D
217    }
218
219  ////
220
221  ////
222}
223
224trait IsomorphismTraverse[F[_], G[_]] extends Traverse[F] with IsomorphismFunctor[F, G] with IsomorphismFoldable[F, G]{
225  implicit def G: Traverse[G]
226  ////
227
228  protected[this] override final def naturalTrans: F ~> G = iso.to
229
230  override def traverseImpl[H[_] : Applicative, A, B](fa: F[A])(f: A => H[B]): H[F[B]] =
231    Applicative[H].map(G.traverseImpl(iso.to(fa))(f))(iso.from.apply)
232  ////
233}