How to send a type parameter as a function argument - scala

I caught myself repeatedly using a similar piece of code for JSON unmarshalling. The only difference between the snippets was the type parameter in a function call. Consequently, I tried to write a function to improve code reuse, but I cannot seem to get it to compile. What I'm attempting to do is shown below.
/** Decode a GET response by unmarshalling its JSON payload.
* #tparam R The type of Response to unmarshall into.
* #param response The GET response to decode.
* #return Try[R] if decoding was successful, else Failure[Throwable] */
private def decodeResponse[R <: Response](response: HttpResponse): Try[R] = {
val payload = decode[R](response.text)
logger.debug(s"Decoded payload: $payload")
payload.toTry
}
As you can see, I wish to specify a type R as part of my return type and part of my function body. I believe it is the latter which is causing compilation to fail, but I am unsure of how to fix it. An example of an R would be SearchResponse, the case class definition for which extends the Response trait.
I've performed several searches into type parameters, but no results use type parameters in function bodies. Additionally, I've searched for the exception that is being thrown upon compilation:
Error:(72, 28) could not find implicit value for evidence parameter of type io.circe.Decoder[R]
val payload = decode[R](response.text)
However, all results lead to solutions for specific libraries that caused these problems, which unfortunately isn't of use for me. Any help would be appreciated!

The decode[R] function requires an implicit parameter of type Decoder[R]. To make your code compile, you need to add this implicit parameter to your own function:
private def decodeResponse[R <: Response](response: HttpResponse)(implicit decoder: Decoder[R]): Try[R] = …
Passing an implicit parameter Foo[A] for some type parameter A is a very common occurrence, which is why they came up with a terser syntax for this use case: Context bounds.
https://docs.scala-lang.org/tutorials/FAQ/context-bounds.html
All it means is that when you write this
def foo[A: Foo] = …
it will be equivalent to this:
def foo[A](implicit f: Foo[A])

Related

How do I unmarshaling generic type that is used as a return value of a method?

I'm quite new to scala, I will appreciate if you can help me with the following question.
i'm using akka-http to send http request I would like to declare a generic send request method which transforms the http response body using Unmarshall to the generic type.
How should i cast the Unmarshal response to T ???
the send request implementation:
def sendRequest[T](requestMessage :HttpRequestMessage) :Future[T] =
{
val promise = Promise[HttpResponse]()
val request = requestMessage.request -> promise
queue.offer(request).flatMap {
case QueueOfferResult.Enqueued => promise.future.flatMap[AnyRef] {
response => {
response.entity.toStrict(FiniteDuration(3,"seconds")).flatMap {
strict => Unmarshal(strict.getData).to[T]
}
}
}
}
}
If you take a look at the code of Unmarshal object, you can see that the type parameter used in to has a certain constraint - an implicit unmarshaller:
class Unmarshal[A](val value: A) {
/**
* Unmarshals the value to the given Type using the in-scope Unmarshaller.
*/
def to[B](implicit um: Unmarshaller[A, B], ec: ExecutionContext, mat: Materializer): Future[B] = um(value)
}
When unmarshalling a value of type A to a value of type B, there must be an implicit value of type Unmarshaller[A, B] available in scope. There are many predefined unmarshallers (e.g. here are some commonly used ones for converting from String to various types such as Int, Boolean etc.), but you can also define your own. This is known as the type class pattern.
So if you want your code to work for some type T, you must ensure that there is an implicit unmarshaller for that type available in scope. This means that your method sendRequest must have an implicit parameter of type Unmarshaller[Data, T], where Data should be replaced by whatever is the actual type of strict,getData (I can't tell from your code).
So something like this:
def sendRequest[T](requestMessage: HttpRequestMessage)(implicit m: Unmarshaller[Data, T]): Future[T] // replace Data with concrete type
This allows the compilation of to[T], but now you have the obligation to actually have this implicit value in scope at the point of invocation of to[T]. As said earlier, you have two options - either import predefined unmarshallers (such as PredefinedFromStringUnmarshallers shown earlier), or define your own. I can't tell what T can be so I can't advise you further than this, but the main point is that as long as you provide the unmarshaller for the concrete type behind T (via import or define it manually), it should work; otherwise akka will have no idea how to unmarshall to your T.

Scala type signature failing with subclasses

I have the following exception hierarchy defined:
/**
* Base class for all exceptions in this library
*/
trait MyAkkaHttpException {}
/**
* Thrown when there is a problem persisting data to a datastore
*/
case class PersistenceException(message: String)
extends Exception(message: String) with MyAkkaHttpException
/**
* Thrown when validation on an object fails
* #param errors
*/
case class ValidationException(message: String, errors: List[String])
extends Exception(message: String) with MyAkkaHttpException
And the following code:
class ContactFormService(contactFormPersistor: ContactFormPersistor) {
def handleForm(contactForm: ContactForm): ValidationNel[MyAkkaHttpException, String] = {
contactForm.validate() match {
case Success(_) => contactFormPersistor.persist(contactForm)
case Failure(e) =>
new ValidationException(message = "Error validating contact form",
errors = e.toList).failureNel[String]
}
}
}
contactFormPersistor.persist returns ValidationNel[PersistenceException, String]
contactForm.validate() returns ValidationNel[String, Boolean]
The problem is handleForm won't accept that PersistenceException and ValidationException are subclasses of MyAkkaHttpException. What do I need to do to make it correctly realise that those return types are valid subclasses?
Try changing ValidationNel[MyAkkaHttpException, String] to Validation[NonEmptyList[MyAkkaHttpException], String]. As someone pointed out in the comments, it's only the type alias that is not covariant in the first type argument.
type ValidationNel[E, +X] = Validation[NonEmptyList[E], X]
Otherwise, NonEmptyList and Validation are both covariant in all their arguments.
EDIT:
This might depend on your version of scalaz. As far as the latest available that I can browse, it looks like ValidationNel is no longer covariant in both arguments, but it previously was. There is probably a good reason for this change: be prepared to not be able to use Scalaz's functions for ValidationNel.
Either is covariant over both the left and right, so I've just switched to that instead.
The problem is you need covariance on the first type parameter of ValidationNel and this particular shortcut of Validation was not designed with this covariance in mind*
Based on the information i gathered from our comment exchange, i believe this is the correct way forward. Declare your own alias (or use the type directly)
type MyValidationNel[+E, +X] = Validation[NonEmptyList[E], X]
*) I do however have a feeling there was a reason behind not having covariance on the E param (as scalaz normally is know to do things with a reason)

Scala - how to go resolve "Value is not a member of Nothing" error

This example code is based on Atmosphere classes, but if someone could give me some insights into what the error means in general, I think I can figure out any Atmosphere-specific solution...
val bc = BroadcasterFactory.getDefault().lookup(_broadcasterId)
bc.broadcast(message)
After the first line, bc should contain a handle to an object whose class definition includes the method broadcast() -- in fact, it contains several overloaded variations. However, the compiler chokes on the second line of code with the following: "value broadcast is not a member of Nothing"
Any ideas/suggestions on what would be causing this?
Thanks.
EDIT: signature for [BroadcasterFactor].lookup :
abstract Broadcaster lookup(Object id)
Note: 1) that is the signature version that I've used in the example, 2) it is the java Inteface signature - whereas the getDefault() hands back an instantiated object that implements that interface.
Solution: force type cast on value:
val bc: Broadcaster = BroadcasterFactory.getDefault().lookup(_broadcasterId)
Nothing is the type name. It's the subtype of all other types. You can't call methods from Nothing itself, you have to specify exact type ((bc: ExactType).broadcast(message)). Nothing has no instances. Method, that returns Nothing will, actually, never return value. It will throw an exception eventually.
Type inference
Definition of lookup:
abstract public <T extends Broadcaster> T lookup(Object id);
in scala this definition looks this way:
def lookup[T <: Broadcaster](Object id): T
There is not specified type parameter in lookup method. In this case compiler will infer this type parameter as the most specific type - Nothing:
scala> def test[T](i: Int): T = ???
test: [T](i: Int)T
scala> lazy val x = test(1)
x: Nothing = <lazy>
scala> lazy val x = test[String](1)
x: String = <lazy>
You could specify type parameter like this:
val bc = BroadcasterFactory.getDefault().lookup[Broadcaster](_broadcasterId)
Draft implementation
In development process lookup can be "implemented" like this:
def lookup(...) = ???
??? returns Nothing.
You should specify either result type of lookup method like this: def lookup(...): <TypeHere> = ... or type of bc: val bc: <TypeHere> =.

Why the following scala code is valid?

My understanding is Unit = void, but why I can pass in multiple argument?
So can anyone explain why the following code is valid?
def foo(x: Unit) = println("foo")
foo("ss", 1)
If you run your snippet with scala -print you'll roughly get the following output for the code:
/* Definition of foo */
private def foo(x: scala.runtime.BoxedUnit): Unit = {
/* Invocation of foo */
foo({
new Tuple2("ss", scala.Int.box(1));
scala.runtime.BoxedUnit.UNIT
});
As you can see, the arguments to foo are rewritten into a code block that creates a tuple but then returns UNIT.
I can't see a good reason for this behaviour and I'd rather get a compiler error thrown instead.
A related question which gives a decent answer to this is here:
Scala: Why can I convert Int to Unit?
From Section 6.26.1 of the Scala Language Specification v2.9, "Value Discarding":
If e has some value type and the expected type is Unit, e is converted to the expected type by embedding it in the term { e; () }.
So, in your case it seems ("ss", 1) is being converted to a tuple so that it can be treated as a single argument, then as that argument type is not Unit, it is converted to a block which computes that tuple value then returns unit to match with the required type of the parameter.

Why can't I omit "apply" in this.apply(_) in Scala?

Observe the following code
trait Example {
type O
def apply(o: O)
def f(o: O) = this.apply(o)
}
which compiles fine in Scala. I would expect that I can leave out apply as usual, writing def f(o: O) = this(o). However, this results in the exciting error message
type mismatch; found : o.type (with underlying type Example.this.O)
required: _31.O where val _31: Example
possible cause: missing arguments for method or constructor
Can anyone explain to me what's going on?
You can't because this() inside an constructor is a call to this object's constructor (this() anywhere else generates a compilation failure) and can not be made into an apply() call as it would hide the constructor and make it impossible to call another constructor in your object. this(args) is always a call to a constructor method (both in Java and Scala), so when inside your own object, you always have to explicitly call apply(args).
The accepted answer is incorrect. You can infer what the actual problem is from the fact that this compiles fine:
trait Example {
def apply(o: String): String = o
def f(o: String) = this(o)
}
this(...) only represents a call to a constructor when the call site is an auxiliary constructor. The remainder of the time it is a call to apply, just as you imagined.