Diese Präsentation wurde erfolgreich gemeldet.
Wir verwenden Ihre LinkedIn Profilangaben und Informationen zu Ihren Aktivitäten, um Anzeigen zu personalisieren und Ihnen relevantere Inhalte anzuzeigen. Sie können Ihre Anzeigeneinstellungen jederzeit ändern.
Nächste SlideShare
×

# Traversals for all ocasions

1.580 Aufrufe

Veröffentlicht am

Scalar 2018

Veröffentlicht in: Software
• Full Name
Comment goes here.

Are you sure you want to Yes No

### Traversals for all ocasions

1. 1. TRAVERSALS FOR ALL OCCASIONS Luka Jacobowitz
2. 2. Software Developer at codecentric Co-organizer of ScalaDus and IdrisDus Maintainer of cats, cats-effect, cats-mtl, OutWatch Enthusiastic about FP About me
3. 3. Motivation ● Traversable is my favorite type class ● Not enough people know about it ● Even less people know about some of the less common traversals out there ● Have some fun while learning!
4. 4. Motivation
5. 5. Teaser How do you create a List of Http Requests run them all in parallel and if errors occur accumulate them? userIdList.parTraverse(request).value
6. 6. Traverse [T[_]: Traverse, F[_]: Applicative, A]: T[F[A]] => F[T[A]] E.g. List[Future[A]] => Future[List[A]] Vector[Option[A]] => Option[Vector[A]]
7. 7. Traverse [T[_]: Traverse, F[_]: Applicative, A]: T[F[A]] => F[T[A]] Traverse runs an action(F[_]) for every element in a data structure (T[_]), and accumulates the results.
8. 8. Traverse trait Applicative[F[_]] { def map2[A, B, C](fa: F[A], fb: F[B])(f: (A, B) => C): F[C] def pure[A](a: A): F[A] } Applicatives allow us to combine two or more independent values inside a context.
9. 9. Traverse trait Traverse[T[_]] { def sequence[F[_]: Applicative, A](tfa: T[F[A]]): F[T[A]] def traverse[F[_]: Applicative, A, B](ta: T[A], f: A => F[B]): F[T[B]] } t.traverse(f) <-> t.map(f).sequence
10. 10. Traverse List[Future[A]] => Future[List[A]] Vector[Option[A]] => Option[Vector[A]] Either[E, IO[A]] => IO[Either[E, A]] type EitherE[A] = Either[E, A] List[Validated[E, A]] => Validated[E, List[A]]
11. 11. FoldMap trait Foldable[T[_]] { def foldMap[A, M: Monoid](ta: T[A], f: A => M): M def fold[M: Monoid](ta: T[M]): M } t.foldMap(f) <-> t.map(f).fold def foldMap[A, M: Monoid](ta: T[A], f: A => M): M = ta.traverse(a => Const(f(a))).getConst
12. 12. NonEmpty trait Reducible[T[_]] { def reduceMap[A, S: Semigroup](ta: T[A], f: A => S): S def reduce[S: Semigroup](ta: T[S]): S } trait NonEmptyTraverse[T[_]] { def nonEmptyTraverse[F[_]: Apply](ta: T[A], f: A => F[B]): F[T[B]] def nonEmptySequence[F[_]: Apply](ta: T[F[A]]): F[T[A]] } t.reduceMap(f) <-> t.map(f).reduce t.nonEmptyTraverse(f) <-> t.map(f).nonEmptySequence
13. 13. NonEmpty def maximum[A: Order](nel: NonEmptyList[A]): A = reduceMap(nel)(Max) def minimum[A: Order](nel: NonEmptyList[A]): A = reduceMap(nel)(Min)
14. 14. NonEmpty def countWords(text: String): Map[String, Int] = words.split(" ").groupBy(identity).mapValues(_.length) val lines: NonEmptyList[String] val result: Map[String, NonEmptyList[Int]] = lines.nonEmptyTraverse(countWords)
15. 15. Commutativity trait UnorderedFoldable[T[_]] { def unorderedFold[M: CommutativeMonoid](ta: T[M]): M } trait UnorderedTraverse[T[_]] { def unorderedSequence[F[_]: CommutativeApplicative, A] (ta: T[F[A]]): F[T[A]] }
16. 16. Commutativity CommutativeMonoid: a |+| b <-> b |+| a E.g: Int, Set[String]
17. 17. Commutativity val users: HashSet[User] val result = users.unorderedFoldMap(_.billableHours)
18. 18. Commutativity CommutativeApplicative: map2(fa, fb)((a, b) => f(a, b)) <-> map2(fb, fa)((b, a) => f(a, b)) fa *> fb <-> fb <* fa E.g. Option, ValidatedNes
19. 19. Commutativity type ValidatedNes[E, A] = Validated[NonEmptySet[E], A] val result: ValidatedNes[Error, RDD[User]] = users.unorderedTraverse(validate)
20. 20. FlatTraverse trait Traverse[T[_]] { def flatTraverse[G[_]: Applicative, A, B](ta: T[A]) (f: A => G[T[B]])(implicit T: FlatMap[T]): G[T[B]] } ta.traverse(f).map(_.flatten) <-> ta.flatTraverse(f)