Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scala, cats, http4s - does not recognize <+> symbol from Http4s

I have created two Http4s routes:

class FirstRoutes[F[_] : Async](service: FirstService[F]) extends Http4sDsl[F] {        
  def routes: HttpRoutes[F] = HttpRoutes.of[F] {
        //... some code
  }
}   

class SecondRoutes[F[_] : Async] extends Http4sDsl[F] {            
    def routes: HttpRoutes[F] = HttpRoutes.of[F] {
    //... some code
    }
}

Now in my main method I would like to call this routes like this:

override def run(args: List[String]): IO[ExitCode] =
    for {
      _ <- {
        val app = {
          //...
          val firstRoutes = new FirstRoutes[F](someService)
          val secondRoutes = new SecondRoutes[F]
          (firstRoutes.routes <+> secondRoutes.routes).orNotFound
        }

But when I compile this code I got an error:

Error:(26, 33) value <+> is not a member of org.http4s.HttpRoutes[Server.F]
          (firstRoutes.routes <+> secondRoutes.routes).orNotFound

It is strange for me, because I can normally use this <+> symbol when I use ctrl+space on route class and also I have good imports:

import cats.effect._
import cats.data._
import org.http4s.server.blaze.BlazeServerBuilder
import cats.effect._
import cats.implicits._

Cannot find out how to fix this and use <+> to call route classes. Maybe it is intellij problem? Can someone help me?

like image 562
Developus Avatar asked Apr 25 '19 21:04

Developus


People also ask

What is http4s in Scala?

Http4s is a minimal, idiomatic Scala interface for HTTP services. Http4s is Scala's answer to Ruby's Rack, Python's WSGI, Haskell's WAI, and Java's Servlets. val http = HttpRoutes .of { case GET -> Root / "hello" => Ok ( "Hello, better world." ) }

What is the http4s ecosystem?

In this article, we introduced the http4s ecosystem that helps us serving API over HTTP. The library fully embraces the functional programming paradigm, using Cats and Cats Effect as building blocks. So, we saw how easy is the definition of routes, handling path and query parameters, and how to encode and decode JSON bodies.

Why should I use Scala?

The pure functional side of Scala is favored to promote composability and easy reasoning about your code. I/O is managed through cats-effect . http4s is built on FS2, a streaming library that provides for processing and emitting large payloads in constant space and implementing websockets.

Why do we need different types of http4s decoders and encoders?

Indeed, we need a different kind of decoder and encoder for every type of content. The http4s library ships with decoders and encoders for a limited type of contents, such as String, File, InputStream, and manages more complex contents using plugin libraries. In our example, the request contains a new director in JSON format.


2 Answers

add this scala option for build.sbt

scalacOptions += "-Ypartial-unification"
like image 194
恵砂川 Avatar answered Nov 12 '22 18:11

恵砂川


Maybe you should read http://eed3si9n.com/herding-cats/import-guide.html

https://blog.softwaremill.com/9-tips-about-using-cats-in-scala-you-might-want-to-know-e1bafd365f88 advice 2)

<+> comes from cats.syntax.semigroupk._.

The following code compiles

import cats.effect.{Async, ExitCode, IO}
import cats.syntax.semigroupk._
import org.http4s.HttpRoutes
import org.http4s.dsl.Http4sDsl
import org.http4s.syntax.kleisli._
import scala.language.higherKinds

class App {

  class FirstRoutes[F[_] : Async](service: FirstService[F]) extends Http4sDsl[F] {
    def routes: HttpRoutes[F] = HttpRoutes.of[F] {
      ???
    }
  }

  class SecondRoutes[F[_] : Async] extends Http4sDsl[F] {
    def routes: HttpRoutes[F] = HttpRoutes.of[F] {
      ???
    }
  }

  trait FirstService[F[_]]

  /*override*/ def run[F[_]: Async](args: List[String]): IO[ExitCode] = {
    val someService: FirstService[F] = ???
    for {
      _ <- {
        val app = {
          //...
          val firstRoutes = new FirstRoutes[F](someService)
          val secondRoutes = new SecondRoutes[F]
          (firstRoutes.routes <+> secondRoutes.routes).orNotFound
        }
        IO(???)
      }
    } yield ExitCode(1)
  }
}
like image 44
Dmytro Mitin Avatar answered Nov 12 '22 19:11

Dmytro Mitin