No implicit view available from AnyVal => org.scalacheck.Prop. [error] property - scalacheck

I have 2 questions
I am trying to learn scalacheck
Question 1)
Here is the test I am writing which is throwing the error. Can you please point to which page from docmentation i should read to understand reason behind this error.
case class Student(name:String, age:Int, mathsScore:Int, scienceScore:Int){
require(name != null ,"Name cannot be blank")
require(age > 3 ,"Age should be more than 3")
require(mathsScore >= 0 , "Score should not be negative")
require(scienceScore >= 0 ,"Score should not be negative")
val totalScore = mathsScore + scienceScore
}
Test is
object CaseStudySpecification extends Properties("Case Study Specification") {
property("nullName") = forAll { (name: String, age: Int, ms: Int, ss: Int) =>
if (name == null)
Prop.throws(classOf[IllegalArgumentException]) {
val x = Student(name, age, ms, ss)
}
}
}
Error is
No implicit view available from AnyVal => org.scalacheck.Prop.
[error] property("nullName") = forAll { (name: String, age: Int, ms: Int, ss: Int) =>
[error] ^
Question 2)
The official documentation gives one example test class as
property("stringLength") = Prop.forAll { s: String =>
val len = s.length
(s+s).length == len+len
}
I also read that it can be written as
val stringLength = Prop.forAll { s: String =>
val len = s.length
(s+s).length == len+len
}
How can i run the second form of test code , as when i run sbt test nothing happens for second version.
Both of the above snippets are in
object Ch3 extends Properties("String") {
}

The signature of Prop.forAll being called requires a function returning Prop (or at least something that can be implicitly converted to Prop) but, as written, the function:
(name: String, age: Int, ms: Int, ss: Int) => {
if (name != null) Prop.throws(...)
}
has an inferred signature of (String, Int, Int, Int) => AnyVal, and there does not exist an implicit conversion into a property. Hence the compilation error. The function could be trivially fixed by making sure it always returns a Boolean as follows:
property("nullName") = forAll { (name: String, age: Int, ms: Int, ss: Int) =>
if (name == null) Prop.throws(classOf[IllegalArgumentException]) {
Student(name, age, ms, ss)
}
else true
}
This results in the implicit Boolean => Prop function being applied, and the code compiles. A more idiomatic fix would be to rewrite the property using the implication operator:
property("nullName") = forAll { (name: String, age: Int, ms: Int, ss: Int) =>
name == null ==>
Prop.throws(classOf[IllegalArgumentException]) {
Student(name, age, ms, ss)
}
}
However it is not a good idea to reject too much of the generated input and since the very first value that scalacheck generates is in fact null, the property ends up as 'undecided' so the test still fails. You could just simplify your property to:
property("nullName") = forAll { (age: Int, ms: Int, ss: Int) =>
Prop.throws(classOf[IllegalArgumentException]) {
Student(null, age, ms, ss)
}
}
As this isn't a scalacheck-specific problem but rather a general Scala one it isn't specifically covered in the scalacheck documentation; you can read up on implicit views for more background.

Related

High order functions in Scala

IM trying to understand the below high order functions in Scala but need some clarifications on the parameters of the functions.
Questions:-
What does the Int => String in the apply function mean?
v: Int indicates that the parameter v is of type Int.
What does the [A](x: A) mean in layout function?
object Demo {
def main(args: Array[String]) {
println( apply( layout, 10) )
}
def apply(f: Int => String, v: Int) = f(v)
def layout[A](x: A) = "[" + x.toString() + "]"
}
f: Int => String means that f is a function with one argument of type Int and with a return type String
def layout[A](x: A) means that parameter x is of type A, which can be of any type. Here are a couple of examples on how to invoke layout:
layout[String]("abc") //returns "[abc]"
layout[Int](123) //returns "[123]"
When main runs it invokes apply with the layout function and the argument 10. This will output "[10]"
The syntax of Int => String means passing a function that accepts Int and returns String.
Here is a useful example for passing function:
case class Person(name: String, lastName: String)
val person = Person("Johnny", "Cage")
def updateName(name: String) = {
updatePerson(_.copy(name = name))
}
def updateLastName(lastName: String) {
updatePerson(_.copy(lastName = lastName))
}
private def updatePerson(transformer: Person => Person): Unit = {
transformer(person)
}
Note how each update function passes the copy constructor.

Scala: Function with dynamic contract as argument

I have the following enum.
object Smth extends Enumeration {
class Value(name: String, func: (String, Int) => Boolean) extends super.Val(name)
private def opA(index: Int) : Boolean ={
index > 0
}
private def opB(x: String, index: Int) : Boolean ={
index > 0 && x.length > 0
}
val x = new Value("X", opA) // type mismatch error for opA
val y = new Value("Y", opB)
}
Enum constructor takes as an argument a function, of type (String, Int) => Boolean. Is it possible to create enum constructor in such a way that it will accept functions with 2 distinct contracts, for example:
(String, Int) => Boolean
(Int) => Boolean
I am trying to avoid using default value for argument, in function definition.
This is how I would like to use it.
if(Smth.x.func(0)) { do smth }
else if(Smth.y.func("str", 0)) { do smthElse }
If you just want default value you can do this:
class Value(val name: String, val func: (String, Int) => Boolean) extends super.Val(name) {
def apply(name: String, func: (Int) => Boolean): Value =
new Value(name, (x -> func("default value", x)))
}

Removing the warning message "on-variable type argument Int in type ... is unchecked" with Scala

I have a function that calculate the tuple values only when the input is a tuple of four integers.
def add(v:Any) = {
if (v.isInstanceOf[(Int, Int, Int, Int)]) {
val v2 = v.asInstanceOf[(Int, Int, Int, Int)]
println(v2._1 + v2._2 + v2._3 + v2._4)
} else {
println("NOP")
}
}
object Main extends App {
add((1,1,1,1))
add((1,2))
}
Main.main(args)
It's working, but I got a warning of "non-variable type argument ... is unchekced" warning.
warning: non-variable type argument Int in type (Int, Int, Int, Int) is
unchecked since it is eliminated by erasure
if (v.isInstanceOf[(Int, Int, Int, Int)]) {
Why this error, and what might be the best way to remove this warning message?
If you actually need to check that the argument is a tuple of four Ints, the correct way to do this is to check each component:
def add(v: Any) = v match {
case (i1: Int, i2: Int, i3: Int, i4: Int) =>
println(i1 + i2 + i3 + i4)
case _ =>
println("NOP")
}
This is caused by type erasure in compile time, you can resolve it by TypeTag:
import scala.reflect.runtime.universe._
def add[T](v:T)(implicit t: TypeTag[T]) = {
if ( t.tpe =:= typeOf[(Int, Int, Int, Int)]) {
val v2 = v.asInstanceOf[(Int, Int, Int, Int)]
println(v2._1 + v2._2 + v2._3 + v2._4)
} else {
println("NOP")
}
}
You can replace instanceOfs with pattern matching and suppress the warning with #unchecked
def add(v: Any) = v match {
case t: (Int, Int, Int, Int) #unchecked =>
println(t._1 + t._2 + t._3 + t._4)
case _ =>
println("NOP")
}
if you pass a Tuple4 that is not (Int, Int, Int, Int) you will get a ClassCastException
Error clearly says that generic types of tuple will be removed due to type erasure and hence compiler can't assure that this will work in runtime, it will only see if Tuple4 was passed, not what it contains.
The solution I presented would cause you trouble if it is possible that the function would be called with other than (Int, Int, Int, Int) Tuple4, and then you should proceed with TypeTags, otherways it just looks so much cleaner and doesn't need reflection.

Passing function to overloaded method in Scala

I've hit an interesting issue with passing function references to overloaded methods in Scala (Using 2.11.7)
The following code works as expected
def myFunc(a: Int, b: String): Double = {
a.toDouble + b.toDouble
}
def anotherFunc(value: String, func: (Int, String) => Double) = {
func(111, value)
}
anotherFunc("123123", myFunc)
But the following code doesn't compile
def myFunc(a: Int, b: String): Double = {
a.toDouble + b.toDouble
}
def anotherFunc(value: String, func: (Int, String) => Double) = {
func(111, value)
}
def anotherFunc(value: Int, func: (Int, String) => Double) = {
func(value, "123123")
}
anotherFunc("123123", myFunc)
Compiler shouts the following
scala> anotherFunc("123123", myFunc)
<console>:13: error: type mismatch;
found : String("123123")
required: Int
anotherFunc("123123", myFunc)
Are you using Scala REPL? One of it's design decisions is that if you have two variables/functions with the same name defined then "last defined wins". In your case it is a function with Int parameter.
You can print all defined symbols in REPL using:
$intp.definedTerms.foreach(println)
Here someone had similar question: Why its possible to declare variable with same name in the REPL?
I don't know the reason but seems you have to write
anotherFunc("123123", myFunc _)
to make it work.

How can I specify multiple constructors in the case class?

I'm trying to create a case class with multiple constructors:
object App {
def main(args: Array[String]) {
val a = Something("abc", 100500, _ % 2 == 0)
val b = Something(true, 10, 20)
println(s"$a - $b")
}
}
case class Something(s: String, n: Int, p: Int => Boolean) {
/*
Additional constructor -- Wrong way! -- it is imposible to invoke it outside the class
def this(b: Boolean, x: Int, y: Int) {
this("", 0, (i: Int) => i % x + y == 0)
}
*/
}
So far my code doesn't work:
Error:(10, 23) type mismatch;
found : Boolean(true)
required: String
val b = Something(true, 10, 20)
^
To fix it I need to create a companion object to hold an apply function which represents a new constructor for Something class:
object Something {
def apply(b: Boolean, x: Int, y: Int) = {
new Something(if (b) "" else "default", 0, _ => {
(x + y) % 2 == 0
})
}
}
It is inconvenient. Maybe there is some other way to place multiple constructors into the case class?
Actually it works, but you have to use new as auxiliary constructors do not have apply generated for case class:
case class Something(s: String, n: Int, p: Int => Boolean) {
def this(b: Boolean, x: Int, y: Int) {
this("", 0, (i: Int) => i % x + y == 0)
}
}
new Something(true, 5, 5) // Works
If you want Something(true, 5, 5) to work, you need to create companion object as you said. I think this is because otherwise case class won't be able to work with pattern matching as it is now, or it would have been much more complicated. And notice that pattern matching won't work in this case
Also remember that case class supports default constructors like case class Something(s: String = "default") this might help you, but it does not fix your example unfortunately