How do I use "writeOutputStream" with an fs2 Stream[IO, Byte] - scala

I am trying to use fs2.io.writeOutputStream for the output to a Java AWS lambda fn. I don't know how to provide the implicit parameter it's looking for:
"no implicits found for parameter cs: ContextShift[IO]"
I found some documentation for creating my own implicit ContextShift object but that seems like overkill for what I'm trying to do.
final def handleRequest(in: InputStream, out: OutputStream, context: Context): Unit = (for {
bytes <- in.compile.toList
str = getString(bytes)
args <- decode(str).raiseIO
_ <- produce(args).to(writeOutputStream(IO(out), global)).compile.drain
} yield Unit).unsafeRunAsyncAndForget() // throws exception in the case of Failure
// ------------------------------------------------
// produce(args: MyCaseClass): fs2.Stream[IO, Byte]

"By default, Cats Effect can provide instance of ContextShift[IO] that manages thread-pools, but only if there’s an ExecutionContext in scope or if IOApp is used."
-- Cats-effect documentation.
From an ExecutionContext.
import cats.effect.{IO, ContextShift}
import scala.concurrent.ExecutionContext.Implicits.global
val contextShift = IO.contextShift(global)
Using IOApp.
import cats.effect.{IO, IOApp, ContextShift}
object Main extends IOApp {
override def run(args: List[String]): IO[ExitCode] = {
val cs = implicitly[ContextShift[IO]]
}
}

Related

Scala logging : Log4cats ambigious implicits

I'm a newbie, and I want to test log4cats library for managing scala logging. I can't seem to grasp the intuition behind, I tried testing the example on the documentation but I can't seem to get it working.
Here is what I have tried :
import io.chrisdavenport.log4cats.Logger
import io.chrisdavenport.log4cats.slf4j.Slf4jLogger
import cats.effect.{ExitCode, IO, IOApp, Sync}
import cats.implicits._
object Thing extends IOApp {
// Impure But What 90% of Folks I know do with log4s
implicit def unsafeLogger[F[_]: Sync] = Slf4jLogger.getLogger[F]
// Arbitrary Local Function Declaration
def doSomething[F[_]: Sync]: F[Unit] =
Logger[F].info("Logging Start Something") *>
Sync[F].delay(println("I could be doing anything")).attempt.flatMap {
case Left(e) => Logger[F].error(e)("Something Went Wrong")
case Right(_) => Sync[F].pure(())
}
override def run(args: List[String]): IO[ExitCode] = {
//implicitly[Sync[IO]]
doSomething
IO(ExitCode.Success)
}
}
I'm getting this error: diverging implicit expansion for type cats.effect.Sync[F]

FS2: How to get a java.io.InputStream from a fs2.Stream?

Say I have val fs2Stream: Stream[IO, Byte] and I need to, for example, call some Java library that requires a java.io.InputStream.
I suppose that I'm way too new to FS2, but I cannot seem to find the answer. I've tried to use fs2.io.toInputStream and fs2.io.readInputStream but I cannot figure out how to provide some of the required parameters. I've scoured the almighty Google for answers, but it seems that the API has changed since most people were last looking for an answer.
How can I go about doing something like the following?
def myFunc(data: fs2.Stream[IO, Byte]): InputStream[Byte] = someMagicalFunction(data)
You probably want something like this:
import cats.effect.{ContextShift, IO, Resource}
import java.io.InputStream
def myFunc(data: fs2.Stream[IO, Byte])
(implicit cs: ContextShift[IO]): Resource[IO, InputStream] =
data.through(fs2.io.toInputStream).compile.resource.lastOrError
Then you can use it like:
object JavaApi {
def foo(is: InputStream): IO[Unit] = ???
}
object Main extends IOApp {
def data: fs2.Stream[IO, Byte] = ???
override def run(args: List[String]): IO[ExitCode] =
myFunc(data).use(JavaApi.foo).as(ExitCode.Success)
}
Here is an Scastie with the code running.

Where is the implicit value for parameter P: cats.Parallel[cats.effect.IO,F]

Running the example code snippet under the subtopic parSequence in Cats Effect document throws an error,
import cats._, cats.data._, cats.syntax.all._, cats.effect.IO
val anIO = IO(1)
val aLotOfIOs = NonEmptyList.of(anIO, anIO)
val ioOfList = aLotOfIOs.parSequence
<console>:44: error: could not find implicit value for parameter P: cats.Parallel[cats.effect.IO,F]
I include implicit Timer[IO] i.e. implicit val timer = IO.timer(ExecutionContext.global) but it does not work. Please advise. Thanks
Update #1
For a complete working snippet,
import cats._, cats.data._, cats.syntax.all._, cats.effect.IO
import scala.concurrent.ExecutionContext.Implicits.global
implicit val contextShift = IO.contextShift(global)
val anIO = IO(1)
val aLotOfIOs = NonEmptyList.of(anIO, anIO)
val ioOfList = aLotOfIOs.parSequence
The implicit you're looking for is defined in cats.effect.IOInstances and you can bring it in scope by importing cats.effect.IO._.
private[effect] abstract class IOInstances extends IOLowPriorityInstances {
//....
implicit def ioParallel(implicit cs: ContextShift[IO]): Parallel[IO, IO.Par] =
new Parallel[IO, IO.Par] {
final override val applicative: Applicative[IO.Par] =
parApplicative(cs)
final override val monad: Monad[IO] =
ioConcurrentEffect(cs)
final override val sequential: ~>[IO.Par, IO] =
new FunctionK[IO.Par, IO] { def apply[A](fa: IO.Par[A]): IO[A] = IO.Par.unwrap(fa) }
final override val parallel: ~>[IO, IO.Par] =
new FunctionK[IO, IO.Par] { def apply[A](fa: IO[A]): IO.Par[A] = IO.Par(fa) }
}
}
object IO extends IOInstances {
// ...
}
Note that you will need to have an implicit ContextShift[IO] in scope if you want to use the ioParallel instance.
It is a common pattern in Scala to have implicit instances defined as part of the companion object for the class (in this case IO).

Scala - implicit macros & materialisation

The use cases for implicit macros is supposed to be the so-called "materialisation" of type class instances.
Unfortunately, the example in the documentation is a bit vague on how that is achieved.
Upon being invoked, the materializer can acquire a representation of T and generate the appropriate instance of the Showable type class.
Let's say I have the following trait ...
trait PrettyPrinter[T]{
def printed(x:T) : String
}
object PrettyPrinter{
def pretty[T](x:T)(implicit pretty:PrettyPrinter[T]) = pretty printed x
implicit def prettyList[T](implicit pretty :PrettyPrinter[T]) = new PrettyPrinter[List[T]] {
def printed(x:List[T]) = x.map(pretty.printed).mkString("List(",", ",")")
}
}
and three test classes
class A(val x:Int)
class B(val x:Int)
class C(val x:Int)
Now I understand that instead of writing the following boilerplate
implicit def aPrinter = new PrettyPrinter[A] {def printed(a:A) = s"A(${a.x})"}
implicit def bPrinter = new PrettyPrinter[B] {def printed(b:B) = s"B(${b.x})"}
implicit def cPrinter = new PrettyPrinter[C] {def printed(c:C) = s"C(${c.x})"}
we should be able to add
implicit def materialise[T] : PrettyPrinter[T] = macro implMaterialise[T]
def implMaterialise[T](c:blackbox.Context):c.Expr[PrettyPrinter[T]] = {
import c.universe._
???
}
to the object PrettyPrinter{...} which then generates the corresponding PrettyPrinters on demand ... how? How do I actually get that "representation of T"?
If I try c.typeOf[T], for example, "No TypeTag available for T".
UPDATE
Trying to use class tags doesn't seem to work either.
implicit def materialise[T:ClassTag] : PrettyPrinter[T] = macro implMaterialise[T]
def implMaterialise[T:ClassTag](c:blackbox.Context):c.Expr[PrettyPrinter[T]] = {
import c.universe._
???
}
results in
Error:(17, 69) macro implementations cannot have implicit parameters other than WeakTypeTag evidences
implicit def materialise[T:ClassTag] : PrettyPrinter[T] = macro implMaterialise[T]
^
update2
Interestingly, using WeakTypeTags doesn't really change anything as
implicit def materialise[T:WeakTypeTag]: PrettyPrinter[T] = macro implMaterialise[T]
def implMaterialise[T](c:blackbox.Context)(implicit evidence : WeakTypeTag[T]):c.Expr[PrettyPrinter[T]]
= {
import c.universe._
???
}
will result in
Error:(18, 71) macro implementations cannot have implicit parameters other than WeakTypeTag evidences
implicit def materialise[T:WeakTypeTag]: PrettyPrinter[T] = macro implMaterialise[T]
^
How do I actually get that "representation of T"?
You need to use c.WeakTypeTag, as hinted at by the compiler message you found in your "UPDATE" section.
This project has a working example that you can adapt: https://github.com/underscoreio/essential-macros/blob/master/printtype/lib/src/main/scala/PrintType.scala
object PrintTypeApp extends App {
import PrintType._
printSymbol[List[Int]]
}
import scala.language.experimental.macros
import scala.reflect.macros.blackbox.Context
import scala.util.{ Try => ScalaTry }
object PrintType {
// Macro that generates a `println` statement to print
// declaration information of type `A`.
//
// This only prints meaningful output if we can inspect
// `A` to get at its definition:
def printSymbol[A]: Unit =
macro PrintTypeMacros.printTypeSymbolMacro[A]
}
class PrintTypeMacros(val c: Context) {
import c.universe._
def printTypeSymbolMacro[A: c.WeakTypeTag]: c.Tree =
printSymbol(weakTypeOf[A].typeSymbol, "")
}

Scala spray-client define implicits for AKKA ActorRefFactory

I'm trying to write a simple HTTP client using Scala and spray-client. I'm basing my client on the examples given on Spray docs.
My issue is that the example is creating a new implicit ActorSystem i.e.
implicit val system = ActorSystem()
but I want my client to be reusable and not create a new ActorSystem.
Here's the gist of my code.
trait WebClient {
def get(url: String)(implicit system: ActorSystem): Future[String]
}
object SprayWebClient extends WebClient {
val pipeline: HttpRequest => Future[HttpResponse] = sendReceive
def get(url: String): Future[String] = {
val r = pipeline (Get("http://some.url/"))
r.map(_.entity.asString)
}
}
But I am getting two compiler errors regarding implicits
implicit ActorRefFactory required: if outside of an Actor you need an implicit ActorSystem, inside of an actor this should be the implicit ActorContext WebClient.scala ...
and
not enough arguments for method sendReceive: (implicit refFactory: akka.actor.ActorRefFactory, implicit executionContext: scala.concurrent.ExecutionContext, implicit futureTimeout: akka.util.Timeout)spray.http.HttpRequest => scala.concurrent.Future[spray.http.HttpResponse]. Unspecified value parameters refFactory, executionContext. WebClient.scala...
How should I change the API definitions?
Here's one solution:
import akka.actor.ActorSystem
import spray.http.{HttpRequest, HttpResponse}
import scala.concurrent.Future
import spray.client.pipelining._
trait WebClient {
def get(url: String): Future[String]
}
class SprayWebClient(implicit system: ActorSystem) extends WebClient {
import system.dispatcher
val pipeline: HttpRequest => Future[HttpResponse] = sendReceive
def get(url: String): Future[String] = {
val r = pipeline (Get("http://some.url/"))
r.map(_.entity.asString)
}
}
and here's another that keeps the original WebClient.get signature:
import akka.actor.ActorSystem
import spray.http.{HttpRequest, HttpResponse}
import scala.concurrent.Future
import spray.client.pipelining._
trait WebClient {
def get(url: String)(implicit system: ActorSystem): Future[String]
}
object SprayWebClient extends WebClient {
def get(url: String)(implicit system: ActorSystem): Future[String] = {
import system.dispatcher
val pipeline: HttpRequest => Future[HttpResponse] = sendReceive
val r = pipeline (Get("http://some.url/"))
r.map(_.entity.asString)
}
}
The second one is a bit more expensive because the pipeline is created anew every time even if it is theoretically static per ActorSystem. I would prefer the first solution and try to find a way to propagate the WebClient through your application (by using the cake pattern, by passing it around explicitly, or by using other dependency injection techniques).