0

I have a simple code:

 override def createContributorsList(url: String, params: String): F[List[Contributor]] = getContributorsFromClient(url, params).fold[List[Contributor]](_ => List(), res => res)

 override def createReposList(organization: String, params: String): F[List[GitRepository]] = getReposFromClient(organization, params).fold[List[GitRepository]](_ => List(), res => res)

This code return list of repositories from github and list of contributions. But now I need to call createContributorsList for every repository I found by createReposList. I have done a for comprehension block:

val stats = new StatisticsRepository[IO](new GitHttpClient[IO])
val res = for {
    repos <- stats.createReposList("github", "")
  } yield repos

It works fine, it found repositories for given organization (github). So I tried do it like this:

val res = for {
    repos <- stats.createReposList("github", "")
    list = repos.foreach(repo => stats.createContributorsList(repo.contributors_url, ""))
  } yield (repos, list)

But list is always empty. I don't know how I could do this without for comprehension, because I operate here on Monads like IO. How I should create a code to loop over every repo from repos and call stats.createContributorsList on everyone?

Developus
  • 1,400
  • 2
  • 14
  • 50

1 Answers1

2

Try flatTraverse

import cats.syntax.flatMap._
import cats.syntax.functor._
import cats.syntax.traverse._
import cats.instances.list._

val res: F[(List[GitRepository], List[Contributor])] = for {
  repos <- stats.createReposList("github", "")
  list <- repos.flatTraverse(repo => stats.createContributorsList(repo.contributors_url, ""))
} yield (repos, list)

foreach return Unit so that's not what you need.

Dmytro Mitin
  • 48,194
  • 3
  • 28
  • 66
  • Is it possible to return simple ` List[Contributor]` instead of `F[...]`? The problem is when I want to run it I always need to use `unsafeRunSync` to get list. Or how I can get `A` from `F[A]`? – Developus Nov 10 '19 at 22:20
  • 1
    You shouldn't want to get `A` from `F[A]`. As soon as you get into monad you continue to work with monad. This is common for all monads (Option, Future, IO...). For example with for-compehensions like `for { a <- ... : F[A]; ...` Normally you run `unsafeRunSync` once, at the very end. – Dmytro Mitin Nov 10 '19 at 22:32
  • 1
    `list` inside `list <- repos.flatTraverse...` has type `List[Contributor]`. – Dmytro Mitin Nov 10 '19 at 22:35