Scala syntax inquiry, return type inference - scala

Code seems trivial but I'm not understanding one thing in the return value:
trait JdbcTemplate {
def query(psc: PreparedStatementCreator,
rowMapper: RowMapper): List[_]
}
What exactly does List[_] mean here? Wouldn't using List[Any] imply the same thing? Where can I read on the differences?

Any is a specific, known (though utterly all-inclusive) type. The use of the underscore as type parameter is a shorthand for a more cumbersome and more general syntax for what is called an "existential type." Existential types are non-specific: They say there's at least one type that could go here. They are the dual of universal quantification that is the interpretation of the more commonly used unbounded type parameters. E.g., def method[T](t: T) .... In this construct, T may be bound to any type whatsoever though at each place where that type is instantiated (every occurrence of a call to that method), it is bound to a specific type.

Given that _ means you don't care about the type and Any is supertype of everything, both are the same.

Related

def layout[A](x: A) = ... syntax in Scala

I'm a beginner of Scala who is struggling with Scala syntax.
I got the line of code from https://www.tutorialspoint.com/scala/higher_order_functions.htm.
I know (x: A) is an argument of layout function
( which means argument x of Type A)
But what is [A] between layout and (x: A)?
I've been googling scala function syntax, couldn't find it.
def layout[A](x: A) = "[" + x.toString() + "]"
It's a type parameter, meaning that the method is parameterised (some also say "generic"). Without it, compiler would think that x: A denotes a variable of some concrete type A, and when it wouldn't find any such type it would report a compile error.
This is a fairly common thing in statically typed languages; for example, Java has the same thing, only syntax is <A>.
Parameterized methods have rules where the types can occur which involve concepts of covariance and contravariance, denoted as [+A] and [-A]. Variance is definitely not in the scope of this question and is probably too much for you too handle right now, but it's an important concept so I figured I'd just mention it, at least to let you know what those plus and minus signs mean when you see them (and you will).
Also, type parameters can be upper or lower bounded, denoted as [A <: SomeType] and [A >: SomeType]. This means that generic parameter needs to be a subtype/supertype of another type, in this case a made-up type SomeType.
There are even more constructs that contribute extra information about the type (e.g. context bounds, denoted as [A : Foo], used for typeclass mechanism), but you'll learn about those later.
This means that the method is using a generic type as its parameter. Every type you pass that has the definition for .toString could be passed through layout.
For example, you could pass both int and string arguments to layout, since you could call .toString on both of them.
val i = 1
val s = "hi"
layout(i) // would give "[1]"
layout(s) // would give "[hi]"
Without the gereric parameter, for this example you would have to write two definitions for layout: one that accepts integers as param, and one that accepts string as param. Even worse: every time you need another type you'd have to write another definition that accepts it.
Take a look at this example here and you'll understand it better.
I also recomend you to take a look at generic classes here.
A is a type parameter. Rather than being a data type itself (Ex. case class A), it is generic to allow any data type to be accepted by the function. So both of these will work:
layout(123f) [Float datatype] will output: "[123]"
layout("hello world") [String datatype] will output: "[hello world]"
Hence, whichever datatype is passed, the function will allow. These type parameters can also specify rules. These are called contravariance and covariance. Read more about them here!

Scala Type Syntax

I've observed that, if I want to make a generic function that can accept a list of any type and return a boolean, I can use the following syntax for a function declaration:
def someFunction[A](l:List[A]):Boolean
However, I can achieve an equivalent function declaration with this syntax as well:
def someFunction(l:List[_]):Boolean
The latter syntax makes sense to me; the underscore indicates a wildcard for a List of any type. However the former is confusing; what's the semantic difference between the two types of syntax, if there is one at all? Note: I noticed I could use [B] or [c] or even [%] in place of the "[A]" in the first syntax example.
The A is a "type parameter". Just like a value parameter, such as your l passed parameter, it is the "name", or place holder, for a some type which might be different at different times (i.e. with different invocations of the method).
In your example the A is unused so, yeah, using _ makes more sense and is clearer, but if you were to return an element from the list then the method return type would be A (or whatever name you want to give that parameter). Using _ as a return type wouldn't make any sense.
List[_] is an unconstrained existential type and shorthand for List[X] forSome {type X <: Any} (which is like List<?> in Java).
In this case, I think the function types (not in Scala syntax) forall A. List[A] -> Boolean and (exists A. List[A]) -> Boolean denote the same things, since in both cases you can only inspect the "shape" of the list; probably there's an equivalence between those types.

Any with type context bound

Disclaimer: I'm not sure I really understand type context bounds... or anything.
Is it possible to define a type in scala that is an instance of a TypeClass where the type can be Any, so long as that type obeys a type context bound.
For example I have some typeclass Printable[T]
Printable is a typeclass for things that can be printed, and it's useful as a type context bound because I might want to have typeclass that can take any type as long as it's printable, like this:
class SomeContainer[T: Printable](value: T)
From what I understand the collections library uses type context bounds like this for things that can be ordered, summed etc.
But what I want is type PrintableAnyCollection = SomeCollection[_: Printable]
That is a collection of values that can be of different types, as long as all those types all obey to type context bound that there exists a Printable[T] for w/e that type.
TLDR:
Collection[Any] almost does what I want because it can hold different types
Collection[T: Printable] Almost does what I want because it enforces that the things in the collection are printable but has the consequence that the collection stores only the one type.
Collection[_: Printable] and/or Collection[Any: Printable] look like they sort of describe what I want but aren't valid syntax.
You're presumably looking for something like this:
// Doesn't work
Collection[T forSome {type T: Printable}]
This doesn't work though and the reason is because context bounds are just sugar for implicit parameters, which are resolved at compile time. In particular, the above type would imply that the implicit resolutions the compiler did would depend on the runtime value of the above type (each different T would need another implicit resolution). In effect you would create a method whose arity in its implicit parameters list could change at runtime.
Suffice it to say that doesn't play nice with Scala.
An alternative is to proactively bundle the implicit parameter in some sort of wrapper type and parameterize your collection on the wrapper as an existential. Thus implicit resolution occurs before the collection is created. Miles Sabin covers it well here.
To briefly summarize that approach, it looks something like the following:
case class PrintableWrapper[T](unwrap: T)(implicit ev: Printable[T])
Collection[PrintableWrapper[T] forSome {type T}]
Actually using the entries of the collection is cumbersome (a spurious pattern match is required to appease Scala's typechecker). The desugared context bound is also required to have an explicit instance of Printable to actually print the entry. See Miles Sabin's answer for more details.
This happens to be one spot where implicits are a slightly cumbersome way of encoding typeclasses.

Force single argument in scala varargs

Given a java class with two methods (taken from mockito):
OngoingStubbing<T> thenReturn(T value);
OngoingStubbing<T> thenReturn(T value, T... values);
If I invoke from scala with
....thenReturn("something")
I get an error:
Description Resource Path Location Type
ambiguous reference to overloaded definition, both method thenReturn in trait OngoingStubbing of type (x$1: java.lang.Object, x$2: <repeated...>[java.lang.Object])org.mockito.stubbing.OngoingStubbing[java.lang.Object] and method thenReturn in trait OngoingStubbing of type (x$1: java.lang.Object)org.mockito.stubbing.OngoingStubbing[java.lang.Object] match argument types (java.lang.String)
And I cannot figure out how to fix this.
This is a known Scala-Java interoperability problem, though it's unfortunately not in the FAQ. Here's the Scala ticket describing the problem. Essentially, both methods are applicable when you give a single argument, and the Scala compiler currently doesn't have any heuristic to decide which one is "more specific". Alexey Romanov's approach to always use the varargs version is a good workaround:
thenReturn("something", Nil: _*)
There is also a question running into a similar problem with JCommander. One of the answers there gives a clever workaround using structural types. This approach will use reflection behind the scenes, so you may or may not want to go that direction. For your use case, it would look something like:
type useSingleArgVersion = { def thenReturn(value: AnyRef): OngoingStubbing }
(...).asInstanceOf[useSingleArgVersion].thenReturn("something")
Finally, there is a similar question running into a similar problem with mokito. It doesn't really provide any workarounds, but it does describe the problem in a bit more detail, if you're interested in the reason this happens.
If calling the vararg version is acceptable,
thenReturn("something", Nil: _*)
Can't think of a way to call the method without varargs right now.
These answers are all to the wrong question. The difference is subtle, but this is not the same issue as the one in the linked ticket. That one does require unreasonable gymnastics to call the non-varargs method. For this one, the following is enough.
thenReturn[String]("something")
Or, if you didn't want to do that for some reason, you don't need the type alias and the cast. You can use a structural type ascription directly.
(this: { def thenReturn[T](s: T): OngoingStubbing[T] }).thenReturn("something")
The issue here is type inference at the intersection of overloading and polymorphism - one method is more specific, but scalac doesn't figure out which. The issue in SI-2991 is genuine ambiguity due to an interaction between overloading and tuple conversion - neither is more specific.
Assuming others will find this question when having the overloaded method value thenReturn with alternatives error, I want to share my solution as well.
Instead of
when(field.getValue(isA(classOf[Record]))).thenReturn(value)
I use
doReturn(value).when(field).getValue(isA(classOf[Record]))
which resolves the disambiguity in my case.
The workaround is quite easy:
OngoingStubbing<T> thenReturn(T value);
OngoingStubbing<T> thenReturn(T value1, T valu2, T... values);
There is no "varargs must be non empty" feature.
I tried Steve's solution and got a huge compiler error including:
scala.tools.nsc.symtab.Types$TypeError: type mismatch;
found : scala.reflect.Manifest[Nothing]
required: scala.reflect.ClassManifest[B]
Note: Nothing <: B, but trait ClassManifest is invariant in type T.
You may wish to investigate a wildcard type such as `_ <: B`. (SLS 3.2.10)
I was able to make it work with something like:
thenReturn("something", Seq.empty[Object]: _*)

How to determine type parameter's variance?

Inspired by Real-world examples of co- and contravariance in Scala I thought a better question would be:
When designing a library, are there a specific set of questions you should ask yourself when determining whether a type parameter should be covariant or contravariant? Or should you make everything invariant and then change as needed?
Well, simple, does it make sense? Think of Liskov substitution.
Co-variance
If A <: B, does it make sense to pass a C[A] where a C[B] is expected? If so, make it C[+T]. The classic example is the immutable List, where a List[A] can be passed to anything expecting a List[B], assuming A is a subtype of B.
Two counter examples:
Mutable sequences are invariant, because it is possible to have type safety violations otherwise (in fact, Java's co-variant Array is vulnerable to just such things, which is why it is invariant in Scala).
Immutable Set is invariant, even though its methods are very similar to those of an immutable Seq. The difference lies with contains, which is typed on sets and untyped (ie, accept Any) on sequences. So, even though it would otherwise be possible to make it co-variant, the desire for an increased type safety on a particular method led to a choice of invariance over co-variance.
Contra-variance
If A <: B, does it make sense to pass a C[B] where a C[A] is expected? If so, make it C[-T]. The classic would-be example is Ordering. While some unrelated technical problems prevent Ordering from being contra-variant, it is intuitive that anything that can order a super-class of A can also order A. It follows that Ordering[B], which orders all elements of type B, a supertype of A, can be passed to something expecting an Ordering[A].
While Scala's Ordering is not contra-variant, Scalaz's Order is contra-variant as expected. Another example from Scalaz is its Equal trait.
Mixed Variance?
The most visible example of mixed variance in Scala is Function1 (and 2, 3, etc). It is contra-variant in the parameter it receives, and co-variant in what it returns. Note, though, that Function1 is what is used for a lot of closures, and closures are used in a lot of places, and these places are usually where Java uses (or would use) Single Abstract Method classes.
So, if you have a situation where a SAM class applies, that's likely a place for mixed contra-variance and co-variance.