josiah
josiah

Reputation: 1414

How can I make an instance of a Kleisli of an EitherT in Scala Cats?

I've spent a while hacking on this and still can't quite get the type system to agree with me that this abstraction is really a

ObjectMapper => A => Either[Throwable, B]

My current type looks like

import cats._
import cats.data.{Reader, Kleisli, EitherT}
import cats.implicits._
import com.fasterxml.jackson.databind.{ObjectMapper, JsonNode}

type JsonParser[A, B] = Kleisli[EitherT[Reader[A, ?], Throwable, ?], ObjectMapper, B]

To test instantiating this type, I've written a very simple function that takes a json String and returns an Either[Throwable, JsonNode]

val makeJsonNode: JsonParser[String, JsonNode] =
  Kleisli(mapper => EitherT(Reader(json => tryToEither(Try(mapper.readTree(json))))))

I'm getting this error message:

[info] Compiling 6 Scala sources to .../scala-2.11/classes...
[error] Test.scala:140: missing parameter type
[error]     Kleisli(mapper => EitherT(Reader(json => tryToEither(Try(mapper.readTree(json))))))
[error]             ^
[error] Test.scala:140: missing parameter type
[error]     Kleisli(mapper => EitherT(Reader(json => tryToEither(Try(mapper.readTree(json))))))
[error]                                      ^
[error] Test.scala:140: no type parameters for method apply: (value: F[Either[A,B]])cats.data.EitherT[F,A,B] in object EitherT exist so that it can be applied to arguments (cats.data.Reader[Any,Nothing])
[error]  --- because ---
[error] argument expression's type is not compatible with formal parameter type;
[error]  found   : cats.data.Reader[Any,Nothing]
[error]     (which expands to)  cats.data.Kleisli[cats.Id,Any,Nothing]
[error]  required: ?F[Either[?A,?B]]
[error]     Kleisli(mapper => EitherT(Reader(json => tryToEither(Try(mapper.readTree(json))))))
[error]                       ^
[error] Test.scala:140: type mismatch;
[error]  found   : cats.data.Reader[Any,Nothing]
[error]     (which expands to)  cats.data.Kleisli[cats.Id,Any,Nothing]
[error]  required: F[Either[A,B]]
[error]     Kleisli(mapper => EitherT(Reader(json => tryToEither(Try(mapper.readTree(json))))))
[error]                                     ^
[error] Test.scala:140: no type parameters for method apply: (run: A => F[B])cats.data.Kleisli[F,A,B] in object Kleisli exist so that it can be applied to arguments (<error> => cats.data.EitherT[F,A,B])
[error]  --- because ---
[error] argument expression's type is not compatible with formal parameter type;
[error]  found   : <error> => cats.data.EitherT[F,A,B]
[error]  required: ?A => ?F[?B]
[error]     Kleisli(mapper => EitherT(Reader(json => tryToEither(Try(mapper.readTree(json))))))
[error]     ^
[error] Test.scala:140: type mismatch;
[error]  found   : cats.data.Kleisli[F,A,B]
[error]  required: Test.this.Parser[String,com.fasterxml.jackson.databind.JsonNode]
[error]     (which expands to)  cats.data.Kleisli[[γ$1$]cats.data.EitherT[[β$0$]cats.data.Kleisli[[A]A,String,β$0$],Throwable,γ$1$],com.fasterxml.jackson.databind.ObjectMapper,com.fasterxml.jackson.databind.JsonNode]
[error]     Kleisli(mapper => EitherT(Reader(json => tryToEither(Try(mapper.readTree(json))))))
[error]            ^
[error] 6 errors found
[error] (compile:compileIncremental) Compilation failed
[error] Total time: 2 s, completed Jun 16, 2017 1:28:17 PM

I realize this type is a bit cumbersome and can definitely be improved (and is probably overkill), but I'm digging into this now in the interest of learning more about Cats and the Scala type system for my own personal growth. What is Scala trying to tell me is wrong, here, and how should I fix this?

Upvotes: 1

Views: 427

Answers (1)

Alexey Romanov
Alexey Romanov

Reputation: 170839

The base problem is the missing parameter types, try

Kleisli((mapper: ObjectMapper) => EitherT(Reader((json: String) => tryToEither(Try(mapper.readTree(json))))))

You can only use a lambda without specifying parameter type when there is an expected type giving this information, and in this case makeJsonNode: JsonParser[String, JsonNode] doesn't seem to be enough.

Upvotes: 1

Related Questions