I am playing with tagless final in scala. I use pureconfig to load the configuration and then use the configuration values to set the server port and host. Snippet
def create[F[_]: Async] =
for {
config <- ConfigSource.default.at("shopkart").load[AppConfig]
httpApp = EndpointApp.make[F]
server <- BlazeServerBuilder[F]
.bindHttp(port = config.http.port, host = config.http.host)
.withHttpApp(httpApp)
.resource
} yield server
The compilation error is ambiguous to me. This is the compilation error.
type mismatch;
[error] found : cats.effect.kernel.Resource[F,Unit]
[error] required: scala.util.Either[?,?]
[error] server <- BlazeServerBuilder[F]
[error] ^
[error] one error found
I understand that the ConfigSource.default.at("shopkart").load[AppConfig]
returns Either[ConfigReaderFailures, AppConfig]. But within the context of for-comprehension, it is an instance of AppConfig
. So, why in the following line where BlazeServerbuilder an Either is expected ?
My understanding is with in the context of for-comprehension, these are two different instances. Also, I came across a similar example in scala pet store https://github.com/pauljamescleary/scala-pet-store/blob/master/src/main/scala/io/github/pauljamescleary/petstore/Server.scala#L28
How to de-sugar for to understand this error better?
The code below that you would have got if you have used flatMap/map instead of for-comprehension.
The cause of your error that you can't use different types of a monad in one for-comprehension block. If you need that you should convert your monads to the same type. In your case the easiest way is converting your
Either
toResource[F, AppConfig]
. But you have to consider using F that can understand an error type of Either, like MonadError to handle error from Either and convert it to F. After you can useResource.eval
that expects F. I see that you useAsync
, so you could useAsync[F].fromEither(config)
for that.