Lift checkbox "missing parameter type" error - lift

I can't understand why this code:
var checked = Seq()
SHtml.checkbox(Seq("1","2","3"), null, (checkedList) => checked = checkedList)
give me this error:
missing parameter type
[error] SHtml.checkbox(Seq("1","2","3"), null, (checkedList) => checked = checkedList)
[error] ^
Can anybody help me?

There are two things I see here. First, since you are dealing with a typed Seq, your declaration of checked is likely to cause problems since it is currently Seq[Nothing]. Try changing that to:
var checked = Seq.empty[String]
or
var checked:Seq[String] = Nil
either will give you the correct type for the options you have in the checkbox.
Then, for the actual SHtml.checkbox - the compiler is having trouble inferring the type. I'm not entirely sure why in this case, but since the signature is SHtml.checkbox[T](Seq[T], Seq[T], (Seq[T]) => None). If the type can't be inferred, you can either:
Specify a type for T like:
SHtml.checkbox[String](Seq("1","2","3"), null, (checkedList) => checked = checkedList)
or, explicitly type the input to your function like:
SHtml.checkbox(Seq("1","2","3"), null, (checkedList:Seq[String]) => checked = checkedList)

Related

Mysterious GADT skolem: What type is trying to escape its scope?

Scala 11.2 is giving me this error:
error: type mismatch;
found : Seq[Some[V]]
required: Seq[Option[?V8]] where type ?V8 <: V (this is a GADT skolem)
val output = f(ivs.map(iv => Some(iv.get._1)))
^
First off, this seems like a strange error message: Doesn't Seq[Some[V]] conform to Seq[Option[V]]?
Here are the parts of the surrounding code that seem relevant:
def evalDependencyTree[V]
(linkRelevance: LinkInfo => Option[LinkStrength])
(dtree: DependencyTree[V, LinkInfo], strengthSoFar: LinkStrength = 1.0)
: Option[(V, LinkStrength)] = dtree match {
. . .
case DFunction(f, inputs) => {
val ivs = inputs.map { input =>
evalDependencyTree(linkRelevance)(input, strengthSoFar) // <-- Recursive call
}
val output = f(ivs.map(iv => Some(iv.get._1))) // <-- The line with the error
. . .
}
}
trait DependencyTree[+V, +L]
case class DFunction[V, L](
f: Seq[Option[V]] => Option[V], inputs: Seq[DependencyTree[V, L]])
extends DependencyTree[V, L]
My (very limited) understanding of GADT skolems is that they're types defined by the compiler during type inference, which copy an existing type argument in order to prevent that type from "escaping" its scope, as in a recursive call—that is, to prevent its being referred to from a wider scope that has no access to the type.
I don't see how V could refer to different types in different scopes here. The recursive call to evalDependencyTree has the same type argument, V, as the current call to evalDependencyTree. I tried explicitly writing evalDependencyTree[V] for the recursive call, but the compiler returned the same error message. This code did work when evalDependencyTree did not have a type argument; in that version, dtree was hard-coded to DependencyTree[Int, LinkInfo].
What type is trying to escape? Or rather, what am I doing wrong?
I found a workaround myself: explicitly spell out the full type of f in the pattern-match, like this:
case DFunction(f: Seq[Option[V]] => Option[V], inputs) => . . .
This works, but I'm not accepting it as an answer because I don't have an explanation of why it's necessary. I still don't know when to expect this kind of error or what causes it. If you know, please post an answer!
Also, I would have thought that most of the type explicitly provided for f would have been lost by type erasure. So, there are two important things I can't explain about this workaround.

Migration play from 2.2 to 2.3: No implicit view available from Any

Try to migrate my project from play 2.2.7 to 2.3.8.
The project has the following code:
def setCoordinatesOfAddresses(cardId: Long, caller: Option[Tuple2[Float,Float]] = None, event: Option[Tuple2[Float,Float]] = None) {
Logger.debug("callling SC.setCoordinatesOfAddresses")
DB.withConnection { implicit c =>
try {
val query = SQL("Execute Sc.setCoordinatesOfAddresses {cardId}, {deviceLatitude}, {deviceLongitude}, NULL, NULL, {eventsLatitude}, {eventsLongitude}")
query.on(
"cardId" -> cardId,
"deviceLatitude" -> caller.map(_._1).getOrElse(null),
"deviceLongitude" -> caller.map(_._2).getOrElse(null),
"eventsLatitude" -> event.map(_._1).getOrElse(null),
"eventsLongitude" -> event.map(_._2).getOrElse(null) ).execute()
} catch {
case e: Throwable => Logger.error("error", e)
}
}
Logger.debug("SC.setCoordinatesOfAddresses called")
}
And compiler gives me this error:
Error:(384, 28) Play 2 Compiler:
../app/controllers/Cards.scala:384: No implicit view available from Any => anorm.ParameterValue.
"deviceLatitude" -> caller.map(_._1).getOrElse(null),
^
What should I do to solve this problem?
As I understand from documentation, I need to define parameter types. But I can't understand where and how to do that, in following code.
Try
val ps = Seq[anorm.ParameterValue](yourParameter1,yourParameter2) // Seq[ParameterValue]
SQL("SELECT * FROM test WHERE a={a} b={b}").
on('a -> ps(0), 'b -> ps(1))
You are using parameter of Any(or someother) type but the doc says to use anorm.ParameterValue type
Source
I would suggest to first try val p: ParameterValue = caller.
I think the issue is more that there is no specific parameter conversion for Tuple2[Float,Float] (btw (Float, Float)).
Before Anorm 2.3, unsafe conversion was using .toString (which can lead to a lot of issue).
The better is to convert the tuple to a formatted string, either before passing it as parameter or by adding a custom parameter conversion.
(Anorm doc indicates type safety issues, and how to implement conversion)
The getOrElse(null) is causing your problem. This is because you're calling getOrElse on an Option[Float]. However null in Scala cannot be assigned to a value type like Float. From the scaladoc:
Null is a subtype of all reference types; its only instance is the null reference. Since Null is not a subtype of value types, null is not a member of any such type. For instance, it is not possible to assign null to a variable of type scala.Int.
The same statement applies to Float. Since null and Float do not have a common super-type (other than Any), Scala infers the caller.map(_._1).getOrElse(null) as Any instead Float. This was allowed in Play 2.2.x, however in 2.3.x, Any is no longer allowed to be passed as a parameter because it is not type safe.
The solution? Just remove the getOrElse(null)s and you're good to go. caller.map(_._1) is an Option[Float] which Anorm knows how to handle whether it's empty or not. In general, using null in Scala is bad practice. If you see yourself calling getOrElse(null), you should ask yourself if perhaps there's a better way to handle it safely.

In Scala, why can't I explicitly use a parameter type here?

The codes below works well
List("ios","android","wm").exists(x =>"ios ok".contains(x))
However, if I add the parameter type in the anonymous function like this, it complains type mismatch:
scala> List("ios","android","wm").exists(x: String => "ios ok".contains(x))
<console>:1: error: identifier expected but string literal found.
List("ios","android","wm").exists(x: String => "ios ok".contains(x))
^
If I use _ instead of x, it doesn't compile either:
scala>List("ios","android","wm").exists(_ =>"ios ok".contains(_))
<console>:8: error: missing parameter type for expanded function ((x$2) => "ios ok".<contains: error>(x$2))
Does anyone have ideas about this?
Is there any implicit type conversion happening in these codes?
And how could I use the parameter type explicityly here?
I'm thinking when the compiler sees :String => ... it may be looking to complete a function type like String => A. This is getting triggered by the parentheses, because you'd normally have a typed anonymous function within curly braces.
These work:
List("ios","android","wm").exists((x: String) => x.contains(x))
List("ios","android","wm").exists { x: String => x.contains(x) }
And this last bit doesn't make any sense:
List("ios","android","wm").exists(_ =>"ios ok".contains(_))
The first _ means you don't care what the element is, which is obviously not the case. So the compiler is looking to apply a function with two arguments with an argument list of one.
You want this instead:
List("ios","android","wm").exists("ios ok".contains(_))

type inference in argument list in combination with setter not working

Let's imagine the following items in scope:
object Thing {
var data: Box[String] = Empty
}
def perform[T](setter: Box[T] => Unit) {
// doesn't matter
}
The following fails to compile:
perform(Thing.data = _)
The error message is:
<console>:12: error: missing parameter type for expanded function ((x$1) => Thing.data = x$1)
perform(Thing.data = _)
^
<console>:12: warning: a type was inferred to be `Any`; this may indicate a programming error.
perform(Thing.data = _)
^
While the following compiles:
perform(Thing.data_=)
I have since surpassed this issue by creating a better abstraction, but my curiosity still remains.
Can anyone explain why this is?
Let's expand out what you're doing in the first example:
Thing.data = _
is shorthand for defining an anonymous function, which looks like:
def anon[T](x: Box[T]) {
Thing.data = x
}
So when you call
perform(Thing.data = _)
it's the same as
perform(anon)
The problem is anon and perform take a type parameter T and at no point are you declaring what T is. The compiler can only infer type parameters in a function call from passed arguments, not from within the function body, so it cannot infer in anon that T should be String.
Notice that if you call
perform[String](Thing.data = _)
the compiler has no issue because it now knows what T should be, and if you try to use any type besides string, you'll get a type mismatch error, but the error occurs in the body of the anonymous function, not on the call to perform.
However, when you call
perform(Thing.data_=)
you are passing the method Thing.data_=, which is explicitly defined as Box[String] => Unit, so the compiler can infer perform's type parameter because it is coming from a function argument.

Scala - mapping a list of integers to a method that receives java.lang.Object

Working in Scala-IDE, I have a Java library, in which one of the methods receives java.lang.Object. And I want to map a list of Int values to it. The only solution that works is:
val listOfInts = groupOfObjects.map(_.getNeededInt)
for(int <- listOfInts) libraryObject.libraryMethod(int)
while the following one:
groupOfObjects.map(_.getNeededInt).map(libraryMethod(_)
and even
val listOfInts = groupOfObjects.map(_.getNeededInt)
val result = listOfInts.map(libraryObject.libraryMethod(_))
say
type mismatch; found : Int required: java.lang.Object Note: an
implicit exists from scala.Int => java.lang.Integer, but methods
inherited from Object are rendered ambiguous. This is to avoid a
blanket implicit which would convert any scala.Int to any AnyRef. You
may wish to use a type ascription: x: java.lang.Integer.
and something like
val result = listOfInts.map(libraryObject.libraryMethod(x => x.toInt))
or
val result = listOfInts.map(libraryObject.libraryMethod(_.toInt))
does not work also.
1) Why is it happening? As far as I know, the for and map routines do not differ that much!
2) Also: what means You may wish to use a type ascription: x: java.lang.Integer? How would I do that? I tried designating the type explicitly, like x: Int => x.toInt, but that is too erroneus. So what is the "type ascription"?
UPDATE:
The solution proposed by T.Grottker, adds to it. The error that I am getting with it is this:
missing parameter type for expanded function ((x$3) => x$3.asInstanceOf[java.lang.Object])
missing parameter type for expanded function ((x$3) => x$3.asInstanceOf{#null#}[java.lang.Object]{#null#}) {#null#}
and I'm like, OMG, it just grows! Who can explain what all these <null> things mean here? I just want to know the truth. (NOTE: I had to replace <> brakets with # because the SO engine cut out the whole thing then, so use your imagination to replace them back).
The type mismatch tells you exactly the problem: you can convert to java.lang.Integer but not to java.lang.Object. So tell it you want to ask for an Integer somewhere along the way. For example:
groupOfObjects.map(_.getNeededInt: java.lang.Integer).map(libraryObject.libraryMethod(_))
(The notation value: Type--when used outside of the declaration of a val or var or parameter method--means to view value as that type, if possible; value either needs to be a subclass of Type, or there needs to be an implicit conversion that can convert value into something of the appropriate type.)