Skip to content

Instantly share code, notes, and snippets.

@slouc
Last active August 20, 2019 09:27
Show Gist options
  • Save slouc/ac918be538e8b65c444c28aacdd10da2 to your computer and use it in GitHub Desktop.
Save slouc/ac918be538e8b65c444c28aacdd10da2 to your computer and use it in GitHub Desktop.
import cats._
import cats.implicits._
// F[A] can fold A if F is a Foldable and A is a Monoid
def folding[F[_]: Foldable, A: Monoid](fa: F[A]): A =
implicitly[Foldable[F]].fold(fa)
// Option[A] is a Monoid if A is a Semigroup
def foldingOption[A: Semigroup](a: A): Option[A] =
folding(List(Option(a))) // List is Foldable
foldingOption(34) // Some(34)
// traversing is folding, but instead of semigroup combining, e.g. 1 |+| 2 = 3,
// we perform applicative combining, e.g. G(1) |+| G(List(2, 3, 4)) = G(List(1, 2, 3, 4))
// sequencing is traversing where each element is already an effect G (that is, it's
// traversing with identity)
def traversing[F[_]: Traverse, G[_]: Applicative, A, B](fa: F[A])(f: A => G[B]): G[F[B]] =
implicitly[Traverse[F]].traverse(fa)(f)
def sequencing[F[_]: Traverse, G[_]: Applicative, A](fa: F[A]): G[F[A]] =
implicitly[Traverse[F]].traverse(fa)(a => implicitly[Applicative[G]].pure(a))
traversing(List(35))((i: Int) => Option(i + 100)) // Some(List(135))
def traverseList[G[_]: Applicative, A, B](fa: List[A])(f: A => G[B]): G[List[B]] =
fa.foldRight(Applicative[G].pure(List.empty[B]))(
(a, acc) => Applicative[G].map2(f(a), acc)(_ :: _)
)
traverseList(List(36, 37))((i: Int) => Option(i + 100)) // Some(List(136, 137))
def traverseOption[G[_]: Applicative, A, B](fa: Option[A])(f: A => G[B]): G[Option[B]] =
fa.fold(Applicative[G].pure(Option.empty[B]))(
a => Applicative[G].map(f(a))(Option(_))
)
traverseOption(Option(36))((i: Int) => List(i + 100)) // List(Some(136))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment