opensas
opensas

Reputation: 63415

Scala is not inferring the appropriate method

I have the following method

def show[E: Writes, T: Writes](block: RequestWithUser[AnyContent] => Either[E, T]): Action[AnyContent] = {
  withErr(block)
}

which I use like this from a controller:

def show(id: Long) = CrudAuthAction.show { request =>
  IdeaType.findByIdWithErr(id)
}

And I want the request method to be optional, so I defined another signature for the same method:

def show[E: Writes, T: Writes](block: => Either[E, T]): Action[AnyContent] = {
  withErr(request => block)
}

And it works fine, I can omit the request param

But when I try to do the same with this other method

def list[T: Writes](block: RequestWithUser[AnyContent] => T): Action[AnyContent] = {
  fromRequest(block)
}

def list[T: Writes](block: => T): Action[AnyContent] = {
  fromRequest(request => block)
}

When I want to use it like this:

def list = CrudAuthAction.list { request =>
  IdeaType.find(request.queryString)
}

it tells me that request is missing parameter type, and I have to specify it like this:

def list = CrudAuthAction.list { request: RequestWithUser[AnyContent] =>

I don't see what's different from the first case, but scala can't seem to infer the proper type of request...

The only difference I see is that in the first case, the block is returning an Either[E, T], but in the second case is returning just a generic T...

Upvotes: 6

Views: 125

Answers (1)

Kim Stebel
Kim Stebel

Reputation: 42047

The problem is that in the second example the compiler does not know which of the overloaded methods to pick, because T could well be a function type. Since Either is clearly not a function, it works in the first case.

To work around this issue, you could change the second method to

def list[T: Writes](block: => Foo[T]): Action[AnyContent] = {
  fromRequest(request => block.v)
}

With Foo defined like that:

case class Foo[T](val v:T)

Unfortunately, adding an implicit conversion to Foo breaks things again, unless you create an implicit conversion for each type in the Writes type class.

Upvotes: 5

Related Questions