Translate

sábado, 4 de febrero de 2023

Foldable y Traverse parte 6

Podemos reescribir la poligonal en términos de un Aplicativo. Nuestro acumulador del ejemplo anterior:


Future(List.empty[Int])


es equivalente a Applicative.pure:


import cats.Applicative

import cats.instances.future._ // for Applicative

import cats.syntax.applicative._ // for pure

List.empty[Int].pure[Future]


Nuestro combinador, que solía ser este:


def oldCombine(accum : Future[List[Int]],host: String): Future[List[Int]] = {

val uptime = getUptime(host)

for {

        accum <- accum

        uptime <- uptime

    } yield accum :+ uptime

}


ahora es equivalente a Semigroupal.combine:


import cats.syntax.apply._ // for mapN

// Combining accumulator and hostname using an Applicative:

def newCombine(accum: Future[List[Int]], host: String): Future[List[Int]] =

(accum, getUptime(host)).mapN(_ :+ _)


Al sustituir estos fragmentos en la definición de poligonal, podemos generalizarla para que funcione con cualquier aplicativo:


def listTraverse[F[_]: Applicative, A, B] (list: List[A])(func: A => F[B]): F[List[B]] =

list.foldLeft(List.empty[B].pure[F]) { (accum, item) =>

(accum, func(item)).mapN(_ :+ _)

}


def listSequence[F[_]: Applicative, B] (list: List[F[B]]): F[List[B]] =

listTraverse(list)(identity)


Podemos usar listTraverse para volver a implementar nuestro ejemplo de tiempo de actividad:


val totalUptime = listTraverse(hostnames)(getUptime)

Await.result(totalUptime, 1.second)

// res5: List[Int] = List(1020, 960, 840)


o podemos usarlo con otros tipos de datos de Applicative.