Complex Scala Type Inference w/ Lambda Expressions - scala

I'm working on a DSL for a experimental library I'm building in Scala, and I've run into some vexing peculiarities of Scala's type inference as it pertains to lambda expression arguments that don't seem to be covered in the book Programming In Scala.
In my library, I have a trait, Effect[-T], that is used to represent temporary modifiers that can be applied to an object of type T. I have a object, myEffects, that has a method named += that accepts an argument of type Effect[PlayerCharacter]. Lastly, I have a generic method, when[T], that is used for constructing conditional effects by accepting a conditional expression and another effect as an argument. The signature is as follows:
def when[T](condition : T => Boolean) (effect : Effect[T]) : Effect[T]
When I call the "when" method with the above signature, passing it's result to the += method, it is unable to infer the type of the argument to the lambda expression.
myEffects += when(_.hpLow()) (applyModifierEffect) //<-- Compiler error
If I combine the arguments of "when" into a single parameter list, Scala is able to infer the type of the lambda expression just fine.
def when[T](condition : T => Boolean, effect : Effect[T]) : Effect[T]
/* Snip */
myEffects += when(_.hpLow(), applyModifierEffect) //This works fine!
It also works if I remove the second parameter entirely.
def when[T](condition : T => Boolean) : Effect[T]
/* Snip */
myEffects += when(_.hpLow()) //This works too!
However, for aesthetic reasons, I really want the the arguments to be passed to the "when" method as separate parameter lists.
My understanding from section 16.10 of Programming in Scala is that the compiler first looks at whether the method type is known, and if so it uses that to infer the expected type of it's arguments. In this case, the outermost method call is +=, which accepts an argument of type Effect[PlayerCharacter]. Since the return type of when[T] is Effect[T], and the method to which the result is being passed expects an argument of type Effect[PlayerCharacter], it can infer that T is PlayerCharacter, and therefore the type of the lambda expression passed as the first argument to "when" is PlayerCharacter => Boolean. This seems to be how it works when the arguments are provided in one parameter list, so why does breaking the arguments into two parameter lists break it?

I'm relatively new to Scala myself, and I don't have a lot of detailed technical knowledge of how the type inference works. So best take this with a grain of salt.
I think the difference is that the compiler is having trouble proving to itself that the two Ts are the same in condition : T => Boolean and effect : Effect[T], in the two-parameter-list version.
I believe when you have multiple parameter lists (because Scala views this as defining a method which returns a function that consumes the next parameter list) the compiler treats the parameter lists one at a time, not all together as in the single parameter list version.
So in this case:
def when[T](condition : T => Boolean, effect : Effect[T]) : Effect[T]
/* Snip */
myEffects += when(_.hpLow(), applyModifierEffect) //This works fine!
The type of applyModifierEffect and the required parameter type of myEffects += can help constrain the parameter type of _.hpLow(); all the Ts must be PlayerCharacter. But in the following:
myEffects += when(_.hpLow()) (applyModifierEffect)
The compiler has to figure out the type of when(_.hpLow()) independently, so that it can check if it's valid to apply it to applyModifierEffect. And on its own, _.hpLow() doesn't provide enough information for the compiler to deduce that this is when[PlayerCharacter](_.hpLow()), so it doesn't know that the return type is a function of type Effect[PlayerCharacter] => Effect[PlayerCharacter], so it doesn't know that it's valid to apply that function in that context. My guess would be that the type inference just doesn't connect the dots and figure out that there is exactly one type that avoids a type error.
And as for the other case that works:
def when[T](condition : T => Boolean) : Effect[T]
/* Snip */
myEffects += when(_.hpLow()) //This works too!
Here the return type of when and its parameter type are more directly connected, without going through the parameter type and the return type of the extra function created by currying. Since myEffects += requires an Effect[PlayerCharacter], the T must be PlayerCharacter, which has a hpLow method, and the compiler is done.
Hopefully someone more knowledgeable can correct me on the details, or point out if I'm barking up the wrong tree altogether!

I am a little confused because in my view, none of the versions you say work should, and indeed I cannot make any of them work.
Type inferences works left to right from one parameter list (not parameter) to the next. Typical example is method foldLeft in collections (say Seq[A])
def foldLeft[B] (z: B)(op: (B, A) => B): B
The type of z will makes B known, so op can be written without specifying B (nor A which is known from the start, type parameter of this).
If the routine was written as
def foldLeft[B](z: B, op: (B,A) => B): B
or as
def foldLeft[B](op: (B,A) => B)(z: B): B
it would not work, and one would have to make sure op type is clear, or to pass the B explicity when calling foldLeft.
In your case, I think the most pleasant to read equivalent would be to make when a method of Effect, (or make it look like one with an implicit conversion) you would then write
Effects += applyModifierEffect when (_.hpLow())
As you mentionned that Effect is contravariant, when signature is not allowed for a method of Effect (because of the T => Boolean, Function is contravariant in its first type parameter, and the condition appears as a parameter, so in contravariant position, two contravariants makes a covariant), but it can still be done with an implicit
object Effect {
implicit def withWhen[T](e: Effect[T])
= new {def when(condition: T => Boolean) = ...}
}

Related

When is Nothing a legal receiver?

Being the subtype of every other type allows a hypothetical Nothing typed value to be passed to any function. However, although such a value can serve as receiver for toString() it can't for unary_! (among others).
object Foo {
def dead(q: Nothing): Unit = {
println(q);
q.toString();
((b: Boolean) => !b)(q);
!q; // value unary_! is not a member of Nothing
}
}
Is this a bug or a feature?
Note:
This is the Scala version of an equivalent question I asked on Kotlin.
Upcasting works: !(q.asInstanceOf[Boolean])
You don't need upcasting. You only have to ascribe some type which has a method unary_!:
def dead(q: Nothing): Unit = {
!(q: Boolean)
}
Without an explicit type ascription, the method unary_! simply cannot be resolved, because even though Nothing is a subtype of Boolean, it's not a subclass of Boolean, therefore the compiler can not find a method unary_! in the inheritance hierarchy of Nothing.
The fact that you can define such methods and functions is not a bug either. The following is a completely valid program that uses a function with input type Nothing to produce a perfectly meaningful result 0, without throwing any errors or anything like it:
def foo[X](xs: List[X], f: (Int, X) => Int) = {
xs.foldLeft(0)(f)
}
foo(Nil, (i: Int, n: Nothing) => 42)
The presence of Nothing in the type system is a Really Good Idea, because it's an initial object (for each other type A, there is exactly one function Nothing => A), and it simplifies lot of things, because it does not force you to deal with all kind of strange corner cases.
Nothing is a subtype of every other type (including scala.Null); there exist no instances of this type
In other words, there are no values of type Nothing. So contrary to the statement in your question, you can't pass a Nothing typed value to any function (even hypothetically) because it doesn't exist, by definition. Neither can it be a receiver for any method because, again, it doesn't exist.
So the bug, if there is one, is that the compiler does not warn you that you have created a function that can never be called.
In this case, println(q) works because Nothing is a subtype of Any, and q.toString works because of an implicit conversion of AnyRef to Object which supports toString. The inline function converts q to Boolean which is also OK, but Object does not support unary_! so !q fails to compile.

Scala understanding signatures

In Scala (Play Framework), I can't understand the type signatures even though I read through all the symbols in here.
For example:
/* matches if a == b */
def equalTo[T](t: => T): BeEqualTo
class BeEqualTo(t: => Any)
extends BeTypedEqualTo[Any]
What on earth do these type signatures even mean?
For example, what exactly is "a" and "b" in the documentation? All I see is "t". Is equalTo a function that takes in a function which returns a value of generic type T?
Another example...
Say I have this line...
status(home).must(equalTo(OK))
According to the IDE, OK is a pattern or symbol of type Int. So OK is an Int? You can monkey-patch an int to give it a function like "must", but how can an Int go inside of "equalTo", a function that takes in a function?
Now some of the type signatures make sense. For example...
def status(of: Future[Result])(implicit timeout: Timeout): Int
^ This is a curried function that takes in a future that returns something of type Result and that sucks in an implicit parameter of type Timeout from somewhere (Scala magic) and returns an Int. "home" is of type "Future[Result]", so it fits inside "status".
But other stuff...
contentType(home).must(beSome.which(_ == "text/html"))
^ My IDE says that beSome is of type
def beSome[T](check: ValueCheck[T]): SomeCheckedMatcher[T]
^ So "beSome" is a function. If that is the case, then how on earth can I appeand ".which()", another function, to it as if it were an object?
Another example...
def which[R : AsResult](f: (U) => R): OptionLikeCheckedMatcher[F, Nothing, U]
^ How on earth do you read these type signatures? "which" takes in "f: (U)", or a variable which we call "f" of type "(U)"? Why the unnecessary parenthesis around the "(U)"? Can't you just say "f: U" and make U be a String if R is a String?
"must" is like this...
def must(m: => Matcher[T]): MatchResult[T]
^ So "must" takes in a function that returns a Matcher. But "which" is passing in an OptionLikeCheckedMatcher. "m: => Matcher[T]" is a function that takes in an "m" and returns a "Matcher[T]". How is that the same as an object of type OptionLikeCheckedMatcher?
Can someone provide a definitive guide as to how to read Scala type signatures?
I think you're getting a little confused with the distinction between a function-valued parameter and a call-by-name parameter. They are similar but not quite the same. In the first example you posted, def equalTo[T](t: => T): BeEqualTo, the : => notation means that the parameter is not evaluated immediately (as it would be if it were declared with just a colon), but every time it is used in an expression. This link might clarify things a bit for you: https://tpolecat.github.io/2014/06/26/call-by-name.html
In another example you posted, def which[R: AsResult](f: (U) => R): OptionCheckedLikeMatcher[F, Nothing, U] takes in a function parameter called f, which accepts a U as its argument and returns a T. The brackets around the U are indeed unnecessary, but they would have been necessary if (for example) f were a function taking 2 parameters of type U - we would then have written it as f: (U, U) => R. The return value of which will be an OptionCheckedMatcher. Assuming that this is a subtype of Matcher (which seems sensible), this is the value which is passed to must.

Scala: please explain the generics involved

Could some one please explain the generics involved in the following code from play framework
class AuthenticatedRequest[A, U](val user: U, request: Request[A]) extends WrappedRequest[A](request)
class AuthenticatedBuilder[U](userinfo: RequestHeader => Option[U],
onUnauthorized: RequestHeader => Result = _ => Unauthorized(views.html.defaultpages.unauthorized()))
extends ActionBuilder[({ type R[A] = AuthenticatedRequest[A, U] })#R]
The ActionBuilder actualy has type R[A], it is getting reassigned, this much I understand. please explain the intricacies of the syntax
The bit that's confusing you is called a "type lambda". If you search for "scala type lambda", you'll find lots of descriptions and explanations. See e.g. here, from which I'm drawing a lot of inspiration. (Thank you Bartosz Witkowski!)
To describe it very simply, you can think of it as a way to provide a default argument to a type constructor. I know, huh?
Let's break that down. If we have...
trait Unwrapper[A,W[_]] {
/* should throw an Exception if we cannot unwrap */
def unwrap( wrapped : W[A] ) : A
}
You could define an OptionUnwrapper easily enough:
class OptionUnwrapper[A] extends Unwrapper[A,Option] {
def unwrap( wrapped : Option[A] ) : A = wrapped.get
}
But what if we want to define an unwrapper for the very similar Either class, which takes two type parameters [A,B]. Either, like Option, is often used as a return value for things that might fail, but where you might want to retain information about the failure. By convention, "success" results in a Right object containing a B, while failure yields a Left object containing an A. Let's make an EitherUnwrapper, so we have an interface in common with Option to unwrap these sorts of failable results. (Potentially even useful!)
class EitherUnwrapper[A,B] extends Unwrapper[B,Either] { // unwrap to a successful result of type B
def unwrap( wrapped : Either[A,B] ) : B = wrapped match {
case Right( b ) => b // we ignore the left case, allowing a MatchError
}
}
This is conceptually fine, but it doesn't compile! Why not? Because the second parameter of Unwrapper was W[_], that is a type that accepts just one parameter. How can we "adapt" Either's type constructor to be a one parameter type? If we needed a version of an ordinary function or constructor with fewer arguments, we might supply default arguments. So that's exactly what we'll do.
class EitherUnwrapper[A,B] extends Unwrapper[B,({type L[C] = Either[A,C]})#L] {
def unwrap( wrapped : Either[A,B] ) : B = wrapped match {
case Right( b ) => b
}
}
The type alias part
type L[C] = Either[A,C]
adapts Either into a type that requires just one type parameter rather than two, by supplying A as a default first type parameter. But unfortunately, scala doesn't allow you to define type aliases just anywhere: they have to live in a class, trait, or object. But if you define the trait in an enclosing scope, you might not have access to the default value you need for type A! So, the trick is to define a throwaway inner class in a place where A is defined, just where you need the new type.
A set of curly braces can (depending on context) be interpreted as a type definition in scala, for a structural type. For instance in...
def destroy( rsrc : { def close() } ) = rsrc.close()
...the curly brace defines a structural type meaning any object with a close() function. Structural types can also include type aliases.
So { type L[C] = Either[A,C] } is just the type of any object that contains the type alias L[C]. To extract an inner type from an enclosing type -- rather than an enclosing instance -- in Scala, we have to use a type projection rather than a dot. The syntax for a type projection is EnclosingType#InnerType. So, we have { type L[C] = Either[A,C] }#L. For reasons that elude me, the Scala compiler gets confused by that, but if we put the type definition in parentheses, everything works, so we have ({ type L[C] = Either[A,C] })#L.
Which is pretty precisely analogous to ({ type R[A] = AuthenticatedRequest[A, U] })#R in your question. ActionBuilder needs to be parameterized with a type that takes one parameter. AuthenticatedRequest takes two parameters. To adapt AuthenticatedRequest into a type suitable for ActionBuilder, U is provided as a default parameter in the type lambda.

What is the point of multiple parameter clauses in function definitions in Scala?

I'm trying to understand the point of this language feature of multiple parameter clauses and why you would use it.
Eg, what's the difference between these two functions really?
class WTF {
def TwoParamClauses(x : Int)(y: Int) = x + y
def OneParamClause(x: Int, y : Int) = x + y
}
>> val underTest = new WTF
>> underTest.TwoParamClauses(1)(1) // result is '2'
>> underTest.OneParamClause(1,1) // result is '2'
There's something on this in the Scala specification at point 4.6. See if that makes any sense to you.
NB: the spec calls these 'parameter clauses', but I think some people may also call them 'parameter lists'.
Here are three practical uses of multiple parameter lists,
To aid type inference. This is especially useful when using higher order methods. Below, the type parameter A of g2 is inferred from the first parameter x, so the function arguments in the second parameter f can be elided,
def g1[A](x: A, f: A => A) = f(x)
g1(2, x => x) // error: missing parameter type for argument x
def g2[A](x: A)(f: A => A) = f(x)
g2(2) {x => x} // type is inferred; also, a nice syntax
For implicit parameters. Only the last parameter list can be marked implicit, and a single parameter list cannot mix implicit and non-implicit parameters. The definition of g3 below requires two parameter lists,
// analogous to a context bound: g3[A : Ordering](x: A)
def g3[A](x: A)(implicit ev: Ordering[A]) {}
To set default values based on previous parameters,
def g4(x: Int, y: Int = 2*x) {} // error: not found value x
def g5(x: Int)(y: Int = 2*x) {} // OK
TwoParamClause involves two method invocations while the OneParamClause invokes the function method only once. I think the term you are looking for is currying. Among the many use cases, it helps you to breakdown the computation into small steps. This answer may convince you of usefulness of currying.
There is a difference between both versions concerning type inference. Consider
def f[A](a:A, aa:A) = null
f("x",1)
//Null = null
Here, the type A is bound to Any, which is a super type of String and Int. But:
def g[A](a:A)(aa:A) = null
g("x")(1)
error: type mismatch;
found : Int(1)
required: java.lang.String
g("x")(1)
^
As you see, the type checker only considers the first argument list, so A gets bound to String, so the Int value for aa in the second argument list is a type error.
Multiple parameter lists can help scala type inference for more details see: Making the most of Scala's (extremely limited) type inference
Type information does not flow from left to right within an argument list, only from left to right across argument lists. So, even though Scala knows the types of the first two arguments ... that information does not flow to our anonymous function.
...
Now that our binary function is in a separate argument list, any type information from the previous argument lists is used to fill in the types for our function ... therefore we don't need to annotate our lambda's parameters.
There are some cases where this distinction matters:
Multiple parameter lists allow you to have things like TwoParamClauses(2); which is automatically-generated function of type Int => Int which adds 2 to its argument. Of course you can define the same thing yourself using OneParamClause as well, but it will take more keystrokes
If you have a function with implicit parameters which also has explicit parameters, implicit parameters must be all in their own parameter clause (this may seem as an arbitrary restriction but is actually quite sensible)
Other than that, I think, the difference is stylistic.

Scala unexpectedly not being able to ascertain type for expanded function

Why, in Scala, given:
a = List(1, 2, 3, 4)
def f(x : String) = { x }
does
a.map(_.toString)
work, but
a.map(f(_.toString))
give the error
missing parameter type for expanded function ((x$1) => x$1.toString)
Well... f() takes a String as a parameter. The construct _.toString has type A <: Any => String. The function f() expects a type of String, so the example above does not type check. It seems that Scala is friendly in this case and gives the user another chance. The error message means: "By my type inference algorithms this does not compile. Put the types in and it might, if it's something I can't infer."
You would have to write the anonymous function longhand in this case, i.e. a.map(n => f(n.toString)). This is not a limitation of type inference, but of the wildcard symbol. Basically, when you write a.map(f(_.toString)), the _.toString gets expanded into an anonymous function inside the closest brackets it can find, otherwise this would lead to enormous ambiguity. Imagine something like f(g(_.toString)). Does this mean f(g(x => x.toString)) or f(x => g(x.toString))? Worse ambiguities would arise for multiple nested function calls. The Scala type checker therefore takes the most logical solution, as described above.
Nitpick: the first line of your code should be val a = List(1,2,3,4) :).