Hi all,
I’m practicing with cats-effect, but I’m facing with a strange compiler error.
This is the exact error:
[error] /full-project-path/createSQLstring.scala:155:54: value ap is not a member of object cats.Applicative
[error] val outSQLString7 : IO[String] = cats.Applicative.ap(outApplicative)(listaOut);
[error] ^
value ap is not a member of object cats.Applicative
This is my actual build.sbt file: build-sbt
And this is the main code I’m trying to get up and running, with some of my tries:
ackage src.main.scala.createSQLPackage
//import cats._
import cats.Applicative._ //OK
//import cats.syntax.functor._
import cats.syntax.applicative._
import cats.effect.{IO, Fiber} //OK
import cats.effect.kernel.Outcome
//import cats.kernel.Monoid
import cats.effect.syntax.all._
import cats.syntax.all._ //OK
//import cats.Functor._
//import cats.Applicative._
//import cats.kernel.Semigroup
//import cats.kernel.Monoid
//import cats.effect.IO;
import cats.effect.instances.all
import src.main.scala.computeMD5Package;
import cats.effect.unsafe.implicits.global
class setSQLRecord(listaZipped : List[IO[Fiber[IO, Throwable, String]]],
timeMarkFiber : IO[Fiber[IO, Throwable, String]],
volume : IO[Int]) {
val concatenaSQLstringValue : List[String] => String = item => concatenaSQLstring(item);
val outApplicative : IO[List[String] => String] = IO(concatenaSQLstringValue);
//val outSQLString : IO[String] = listaOut.ap(outApplicative);
//val outSQLString2 : IO[String] = cats.Applicative.ap(outApplicative)(listaOut);
//val outSQLString3 : IO[String] = cats.Functor.compose(listaOut, outApplicative);
//val outSQLString4 : IO[String] = org.typelevel:`cats-core_2.12:2.9.0`.Functor.compose(listaOut, outApplicative);
//val outSQLString5 : IO[String] = org.typelevel:`cats-effect_2.12:3.4.5`.Applicative.ap(outApplicative)(listaOut);
//val outSQLString6 : IO[String] = cats.Applicative.ap(outApplicative)(listaOut);
val outSQLString7 : IO[String] = cats.Applicative.ap(outApplicative)(listaOut);
//val outSQLString8 : IO[String] = listaOut.org.typelevel:`cats-core_2.12:2.9.0`.Applicative.ap(outApplicative);
I’m not able to figure out wich is the exact sequence of imports to get “ap” or “Functor.compose” be available in my code.
Thank you
I know nothing about cats
but here’s what I can tell:
Here it looks like ap
is a method on an instance of trait Applicative
.
Whereas cats.Applicative
is a companion object, and does not have an ap
function.
So if your outApplicative
is an instance of trait Applicative
(since it’s an instance of IO
I assume it must be), then outApplicative.ap(...)
might work, give that a try maybe?
Backing off for a second: what are you trying to accomplish here?
@spamegg1 is correct that ap
is a method on a trait, not an object, so you can’t just call it like that – it’s going to be a method on an object.
More than that, though, Applicative
(like much of cats) is a type class – in Java terms, basically an adapter object. So while he’s right that you would probably use the Applicative
for IO
, that doesn’t mean that IO
is itself an Applicative
, it means than an Applicative
exists for IO
, and you summon it implicitly.
(It’s actually very rare to call ap
directly – it’s mainly there to be called by other functions.)
I’m worried that you may be jumping ahead too quickly – this is really cats stuff, rather than cats-effect. If you haven’t done a lot with type classes yet, I’d recommend going through the cats documentation (really, I’d recommend a quick read through the short book Scala With Cats) to get comfortable with the type classes and how they work before trying to play with advanced stuff like this.
(Note: you don’t need to know all of this in order to work with cats-effect – I’ve never once actually used ap
directly in cats-effect application code. Most of this stuff is under the hood, intended more for library authors, and can/should be ignored when you’re getting started. You can do an awful lot with IO
before really grokking what’s going on under the hood.)
1 Like
Correct ! I’m not expert. I just have an
IO[List[String]] and need an IO[String] concatenating all the strings in the list itself. I thought that could use an applicative to extract, concat and wrab back in the IO. Otherways a Functor.compose . In every case this error blocks me. It seems that both Functor and Applicative, are not part of the context.
ioListStrings.map(listStrings => listStrings.mkString
That is all you need, just follow the types.
No need to do anything complex.
@BalmungSan beat me to it. Yeah, there’s no need to go anywhere near those complexities – it’s just a map
.
1 Like
Actually, it’s worth talking about why that’s the right answer. Think of it this way:
An IO
is, more or less exactly, an encapsulated algorithm. It’s called “IO” for historical reasons, but that’s the heart of it: it describes a process that will product a result of a particular type. And the map
method on it says what to do next once you have that result – giving you a larger algorithm with that step added.
So your IO[List[String]]
is algorithm saying how to get a List[String]
. By calling map
, you’re saying to take that result, call mkString
on it (to concatenate it), and now you have the final IO[String]
.
That’s the essence of most cats-effect programming – just map
ping and flatMap
ping IO
s, building from smaller to larger algorithms until you have the entire program.
1 Like