Bitraverse
Формальное определение
Bitraverse
- тип, порождающий два несвязанных Traverse
.
Расширяет Bifoldable
и Bifunctor
.
Определение в виде кода на Scala
trait Bitraverse[F[_, _]] extends Bifunctor[F] with Bifoldable[F]:
extension [A, B](fab: F[A, B])
def bitraverse[G[_]: Applicative, C, D](f: A => G[C], g: B => G[D]): G[F[C, D]]
override def bimap[C, D](f: A => C, g: B => D): F[C, D] =
bitraverse[Id, C, D](a => Id(f(a)), b => Id(g(b))).value
override def bifoldMap[M](f: A => M)(g: B => M)(using ma: Monoid[M]): M =
def toState[X](f: X => M): X => State[M, X] = x => State[M, X](s => (ma.combine(s, f(x)), x))
val state = bitraverse[[X] =>> State[M, X], A, B](toState[A](f), toState[B](g))
state.run(ma.empty)._1
def bisequence[G[_]: Applicative, A, B](x: F[G[A], G[B]]): G[F[A, B]] = x.bitraverse(fa => fa, fb => fb)
/** Extract the Traverse on the first param. */
def leftTraverse[R]: Traverse[[X] =>> F[X, R]] =
new Traverse[[X] =>> F[X, R]]:
extension [A](fab: F[A, R])
override def traverse[G[_]: Applicative, B](f: A => G[B]): G[F[B, R]] =
fab.bitraverse(f, summon[Applicative[G]].unit)
/** Extract the Traverse on the second param. */
def rightTraverse[L]: Traverse[[X] =>> F[L, X]] =
new Traverse[[X] =>> F[L, X]]:
extension [A](fab: F[L, A])
override def traverse[G[_]: Applicative, B](f: A => G[B]): G[F[L, B]] =
fab.bitraverse(summon[Applicative[G]].unit, f)
/** Unify the traverse over both params. */
def uTraverse: Traverse[[X] =>> F[X, X]] =
new Traverse[[X] =>> F[X, X]]:
extension [A](fab: F[A, A])
override def traverse[G[_]: Applicative, B](f: A => G[B]): G[F[B, B]] =
fab.bitraverse(f, f)
Примеры
Either
given Bitraverse[Either] with
extension [A, B](fab: Either[A, B])
override def bitraverse[G[_]: Applicative, C, D](f: A => G[C], g: B => G[D]): G[Either[C, D]] =
fab match
case Right(value) => g(value).map(d => Right(d))
case Left(value) => f(value).map(c => Left(c))
Ссылки: