Home > Enterprise >  Cats: Map with a function which results in F[_]
Cats: Map with a function which results in F[_]

Time:12-06

I have a function:

def mapIt(id: Int): F[String]

What is the best way to map a collection using it, if the result is used in constructor of a case class? I currently do something like this:

List(1, 2, 3, 4).map( id => mapIt(id).map(SomeCaseClass(id, _))).toList.sequence

CodePudding user response:

You can map some Monad[Int] into Monad[SomeCaseClass] just using map function (if F is Monad then it can be converted to List using ListInstances.catsStdInstancesForList from cats.instances.list). After that all you need is just flatMap your list of Int into list of SomeCaseClass:

import cats.Monad
import cats.instances.list._
import scala.language.higherKinds

case class SomeCaseClass(id: Int, name: String)

def mapIt[F[_]: Monad](id: Int): F[String] = Monad[F].pure((id   10).toString)

List(1, 2, 3, 4).flatMap(id => mapIt(id).map(x => SomeCaseClass(id, x)))
//List(
//  SomeCaseClass(1,11), 
//  SomeCaseClass(2,12), 
//  SomeCaseClass(3,13), 
//  SomeCaseClass(4,14)
//)

More detailed explanation

in function mapIt:

def mapIt[F[_]: Monad](id: Int): F[String]

compiler expect some F[_] which should have some Monad implicit. When you call mapIt inside flatMap function, compiler looking for some Monad over the Int:

List(1, 2, 3, 4).flatMap{
  id => mapIt(id) // looking for Monad[Int]
}

and found it in the imported instances: import cats.instances.list._

From ListInstances:

implicit val catsStdInstancesForList: Traverse[List] with Alternative[List] with Monad[List] with CoflatMap[List] =
    new Traverse[List] with Alternative[List] with Monad[List] with CoflatMap[List] { ... }

after it's just working with common Monad and map Int into SomeCaseClass. In the end it's just flatten List of SomeCaseClasses into.

  • Related