How to make a "n to m" restricted int variant in Scala? - scala

I'd like to have types s.a. Int_1to3 or Uint in Scala. Preferably, there'd be a general factory method that can provide any such.
It's mostly for self-documentary purposes, but also the values would be checked on arrival (i.e. via 'assert').
I was somewhat surprised not to have found a solution to this during my initial (google) search. The closest I came to is Unsigned.scala, but that's overkill for my needs.
This must be dead simple?
Just to give an idea on the usage, something like this would be splendid! :)
type Int_1to3= Int_limited( 1 to 3 )
type Uint= Int_limited( _ >= 0 )

I see two potential solutions:
First you can have a look at Unboxed Type Tags. They allow to attach a type a compile time without having to box the integer. The compiler will enforce that they are used when needed, but values are checked at runtime.
From the cited article, you could write something like:
type Tagged[U] = { type Tag = U }
type ##[T, U] = T with Tagged[U]
trait Positive
trait One2Three
type PositiveInt = Int ## Positive
type SmallInt = Int ## One2Three
//Builds a small int
def small(i: Int): SmallInt = {
require( i > 0 && i < 4, "should be between 1 and 3" )
i.asInstanceOf[SmallInt]
}
//Builds a positive int
def positive( i: Int): PositiveInt = {
require( i >= 0, "should be positive" )
i.asInstanceOf[PositiveInt]
}
//Example usage in methods
def mul( i: SmallInt, j: PositiveInt ): PositiveInt = positive(i*j)
Then in the REPL:
scala> mul( small(2), positive(4) )
res1: PositiveInt = 8
scala> mul( small(4), positive(2) ) //RUNTIME ERROR
java.lang.IllegalArgumentException: should be between 1 and 3
scala> mul( 2, positive(2) ) //COMPILE TIME ERROR
<console>:16: error: type mismatch;
found : Int(2)
required: SmallInt
mul( 2, positive(2) )
^
The second solutions may be value classes proposed for Scala 2.10. You can read the SIP-15 to see how to use them.

A "pattern" you can use here is to declare a sealed type with a private constructor as a wrapper around the underlying value, which is restricted to a single point that it can be validated and instantiated. Eg
sealed abstract class Int_1to3(val i:Int)
object Int_1to3 {
def apply(i:Int):Option[Int_1to3] =
if (1.to(3).contains(i)) Some(new Int_1to3(i){}) else None
}
That way, whenever you end up with an instance of some x of type Int_1to3, you have a compile-time guarantee that x.i will be 1, 2 or 3.

Because you have such "low standards", it is enough to do:
def safeInt(i: Int, f: Int => Boolean): Int =
if (f(i)) i else throw new IllegalArgumentException("wrong int")
def int1to3(i: Int) =
safeInt(i, 1 to 3 contains _)
def uInt(i: Int) =
safeInt(i, _ >= 0)
To have this a a type doesn't make much sense when you do not want to enforce the compiler to keep your code safe. This is possible, but as you said, not for your needs.

No, there is nothing like that in the language. The solutions available -- through libraries -- are what you call "overkilL".

Saw the video on Scalatest/Scalatric 3.0 yesterday, and in it #Bill-Venners discussed the PosInt, PozInt types that are very close to what I had been asking in 2012.
He also presented an OddInt sample for us to create such value types ourselves.

Related

Type parameters applied to Scala Function

I am trying to understand the type parameters when applied to a function.
I would like to use Generic Types in the below method but using String and Int for my understanding.
When I define a function as below
def myfunc[Int](f:String => Int):Int = {
Integer.min(1,2)
}
it complains
found : scala.this.Int
required: Int&0
Integer.min(1,2)
However if I remove the return type of the function ( which I understand is not required), it compiles fine.
I am not able to infer why removing the return type makes the compilation successful.
Appreciate your help.
-Amit
Try
def myfunc(f:String => Int):Int = {
Integer.min(1,2)
}
When you write def myfunc[Int](f:String => Int):Int you declare type parameter Int, which hides standard type scala.Int. This is the same as if you declared def myfunc[A](f:String => A):A. When you remove return type it's inferred to be scala.Int, i.e. def myfunc[A](f:String => A) is def myfunc[A](f:String => A):Int
If you want to use generics, first you have to understand that the name of the variable types starts capitalized and they are names, just that so [Int] in your function is the name of the type variable, an example:
object Main extends App{
val f: String => Int = s => 4
println(myfunc(f, "nothing useful"))
def myfunc[A,B](f:A => B, x: A):B = {
f(x)
}
}
here the names are A and B and the return type is of type B
Question: What's the difference between these 3 methods?
def myfunc1[X](f:String => X):X =
Integer.min(1,2)
def myfunc2[Int](f:String => Int):Int =
Integer.min(1,2)
def myfunc3[IDontGetTypeParameters](f:String => IDontGetTypeParameters):IDontGetTypeParameters =
Integer.min(1,2)
Answer: Nothing. From the compiler's point of view they are the same, and they fail to compile for the same reason: each is defined to return the type of the type parameter but tries to return an integer (Scala.Int) instead.
A quick one liner:
def myfunc(f:String => Int):Int = Integer.min(1,2)
It's good trying to make your own examples, but have you tried any examples from books, articles or tutorials? There's probably a good one in Scala for the Impatient by Cay Horstmann.
Here's a decent example from the Tour de Scala:
def listOfDuplicates[A](x: A, length: Int): List[A] = {
if (length < 1)
Nil
else
x :: listOfDuplicates(x, length - 1)
}
Sometimes you can omit the type parameter, but let's ignore that for now and declare the types explicitly:
listOfDuplicates[Int](43, 5) // Should give a list with 43 five times
listOfDuplicates[String]("Hello, world! ", 3) // "Hello, world!" thrice
listOfDuplicates[(Int, Int)]((0, 1), 8) // The pair (0, 1) eight times
This shows that A can be Int, String, (Int, Int) or just about anything else we can think of. Not sure you'd ever have a practical need for this, but you can even do something like this:
def wrapLength(str: String): Int = str.length
listOfDuplicates[String => Int](wrapLength(_), 2)
Here's a Scastie snippet in which you can play around with this.
Your generic type name shouldn't be one of the reserved words in Scala. Int itself is a reserved word for a type.
In this cases, for simplicity and understanding, we use some basic characters like T or R as the generic type if you really keen to use generics for other functions.

Local variables with the same type( generic type parameter) have incompatible type

This issue is related to compiler behavior described in another issue
I think this is related to the way generics are implemented in compiler, and it has something to do with Inner Class compiler feature. I've a similar question and I know that this could be fixed with
if(m.compare(lowerBound.asInstanceOf[m.Measure]) >= 0) {
But I don't want to cast same type to same type all over my code. There should be good explanation why this happens. Should I fill in compiler bug somewhere ?
Without local variable m - error messages get even more weird.
trait MeasureBase {
type Measure <: MeasureBase
def compare(that: Measure): Int
def score: Double
}
case class DocTerm[Measure <: MeasureBase]
(val docID: Long, val measure:Measure)
extends Ordered[DocTerm[Measure]] {
def score = measure.score
def compare(that: DocTerm[Measure]): Int
= measure.compare(that.measure.asInstanceOf[measure.Measure])
}
class WriteCacheIterator[Measure <: MeasureBase]
(data:mutable.ArrayBuffer[DocTerm[Measure]]) {
var position = 0
def Next(lowerBound:Measure):Option[DocTerm[Measure]] = {
if(position < data.size - 1){
val m:Measure = data(position).measure
val b:Measure = lowerBound
if(m.compare(b) >= 0) {
//gives compiler error
//Error:(39, 20) type mismatch;
//found : b.type (with underlying type Measure)
//required: m.Measure
//if(m.compare(b) >= 0) {
}
} else return None
}
}
You have two different definitions for Measure:
the type parameter in DocTerm and other places, which is a subtype of MeasureBase.
a type member inside MeasureBase.
The two have nothing in common (except the name, but they are really different things). There is nothing linking your generic Measure inside WriteCacheIterator to the type member called Measure inside each and every element in your ArrayBuffer. You need to refactor the code to make this constraint explicit.
You could probably refactor the code to only use type parameters (generics) everywhere.
trait MeasureBase[Self <: MeasureBase[Self]] {...}
case class DocTerm[M <: MeasureBase[M](val docID: Long, val measure: M)
...

Nulls in Scala ...why is this possible?

I was coding in Scala and doing some quick refactoring in Intellij, when I stumbled upon the following piece of weirdness...
package misc
/**
* Created by abimbola on 05/10/15.
*/
object WTF extends App {
val name: String = name
println(s"Value is: $name")
}
I then noticed that the compiler didn't complain, so I decided to attempt to run this and I got a very interesting output
Value is: null
Process finished with exit code 0
Can anyone tell me why this works?
EDIT:
First problem, the value name is assigned a reference to itself even though it does not exist yet; why exactly does the Scala compiler not explode with errors???
Why is the value of the assignment null?
1.) Why does the compiler not explode
Here is a reduced example. This compiles because through given type a default value can be inferred:
class Example { val x: Int = x }
scalac Example.scala
Example.scala:1: warning: value x in class Example does nothing other than call itself recursively
class Example { val x: Int = x }
This does not compile because no default value can be inferred:
class ExampleDoesNotCompile { def x = x }
scalac ExampleDoesNotCompile.scala
ExampleDoesNotCompile.scala:1: error: recursive method x needs result type
class ExampleDoesNotCompile { def x = x }
1.1 What happens here
My interpretation. So beware: The uniform access principle kicks in.
The assignment to the val x calls the accessor x() which returns the unitialized value of x.
So x is set to the default value.
class Example { val x: Int = x }
^
[[syntax trees at end of cleanup]] // Example.scala
package <empty> {
class Example extends Object {
private[this] val x: Int = _;
<stable> <accessor> def x(): Int = Example.this.x;
def <init>(): Example = {
Example.super.<init>();
Example.this.x = Example.this.x();
()
}
}
} ^
2.) Why the value is null
The default values are determined by the environment Scala is compiled to.
In the example you have given it looks like you run on the JVM. The default value for Object here is null.
So when you do not provide a value the default value is used as a fallback.
Default values JVM:
byte 0
short 0
int 0
long 0L
float 0.0f
double 0.0d
char '\u0000'
boolean false
Object null // String are objects.
Also the default value is a valid value for given type:
Here is an example in the REPL:
scala> val x : Int = 0
x: Int = 0
scala> val x : Int = null
<console>:10: error: an expression of type Null is ineligible for implicit conversion
val x : Int = null
^
scala> val x : String = null
x: String = null
why exactly does the Scala compiler not explode with errors?
Because this problem can't be solved in the general case. Do you know the halting problem? The halting problem says that it is not possible to write an algorithm that finds out if a program ever halts. Since the problem of finding out if a recursive definition would result in a null assignment can be reduced to the halting problem, it is also not possible to solve it.
Well, now it is quite easy to forbid recursive definitions at all, this is for example done for values that are no class values:
scala> def f = { val k: String = k+"abc" }
<console>:11: error: forward reference extends over definition of value k
def f = { val k: String = k+"abc" }
^
For class values this feature is not forbidden for a few reasons:
Their scope is not limited
The JVM initializes them with a default value (which is null for reference types).
Recursive values are useful
Your use case is trivial, as is this:
scala> val k: String = k+"abc"
k: String = nullabc
But what about this:
scala> object X { val x: Int = Y.y+1 }; object Y { val y: Int = X.x+1 }
defined object X
defined object Y
scala> X.x
res2: Int = 2
scala> Y.y
res3: Int = 1
scala> object X { val x: Int = Y.y+1 }; object Y { val y: Int = X.x+1 }
defined object X
defined object Y
scala> Y.y
res4: Int = 2
scala> X.x
res5: Int = 1
Or this:
scala> val f: Stream[BigInt] = 1 #:: 1 #:: f.zip(f.tail).map { case (a,b) => a+b }
f: Stream[BigInt] = Stream(1, ?)
scala> f.take(10).toList
res7: List[BigInt] = List(1, 1, 2, 3, 5, 8, 13, 21, 34, 55)
As you can see it is quite easy to write programs where it is not obvious anymore to which value they will result. And since the halting problem is not solvable we can not let the compiler do the work for us in non trivial cases.
This also means that trivial cases, as the one shown in your question, could be hardcoded in the compiler. But since there can't exist a algorithm that can detect all possible trivial cases, all cases that are ever found need to be hardcoded in the compiler (not to mention that a definition of a trivial case does not exist). Therefore it wouldn't be wise to even start hardcoding some of these cases. It would ultimately result in a slower compiler and a compiler that is more difficult to maintain.
One could argue that for an use case that burns every second user it would be wise to at least hardcode such an extreme scenario. On the other hand, some people just need to be burned in order to learn something new. ;)
I think #Andreas' answer already has the necessary info. I'll just try to provide additional explanation:
When you write val name: String = name at the class level, this does a few different things at the same time:
create the field name
create the getter name()
create code for the assignment name = name, which becomes part of the primary constructor
This is what's made explicit by Andreas' 1.1
package <empty> {
class Example extends Object {
private[this] val x: Int = _;
<stable> <accessor> def x(): Int = Example.this.x;
def <init>(): Example = {
Example.super.<init>();
Example.this.x = Example.this.x();
()
}
}
}
The syntax is not Scala, it is (as suggested by [[syntax trees at end of cleanup]]) a textual representation of what the compiler will later convert into bytecode. Some unfamiliar syntax aside, we can interpret this, like the JVM would:
the JVM creates an object. At this point, all fields have default values. val x: Int = _; is like int x; in Java, i.e. the JVM's default value is used, which is 0 for I (i.e. int in Java, or Int in Scala)
the constructor is called for the object
(the super constructor is called)
the constructor calls x()
x() returns x, which is 0
x is assigned 0
the constructor returns
as you can see, after the initial parsing step, there is nothing in the syntax tree that seems immediately wrong, even though the original source code looks wrong. I wouldn't say that this is the behavior I expect, so I would imagine one of three things:
Either, the Scala devs saw it as too intricate to recognize and forbid
or, it's a regression and simply wasn't found as a bug
or, it's a "feature" and there is legitimate need for this behavior
(ordering reflects my opinion of likeliness, in decreasing order)

Array of elements of compound type

I have been playing lately with compound types and I recently was trying the following code:
import scala.reflect._
object Main {
def main(args: Array[String]) {
val a1 = classTag[Int with String with Double].newArray(3)
println(a1.mkString(" "))
val a2 = classTag[String with Int with Double].newArray(3)
println(a2.mkString(" "))
val a3 = classTag[Double with Int with String].newArray(3)
println(a3.mkString(" "))
}
}
With the following output:
0 0 0
null null null
0.0 0.0 0.0
It results a bit strange to me. Each of the array elements has access to the methods of the three types: Int, String and Double. What is happening exactly behind scene here? The compound types are actually instances of the first type? Can a compound type being instanced explicitly? Their use case is only for when the types composing the compound are related through inheritance and so on? Thanks.
P.S.: I'm using Scala 2.11.4
What is happening exactly behind scene here? The compound types are actually instances of the first type?
Looking at the newArray method as defined for ClassTag:
override def newArray(len: Int): Array[T] =
runtimeClass match {
case java.lang.Byte.TYPE => new Array[Byte](len).asInstanceOf[Array[T]]
case java.lang.Integer.TYPE => new Array[Int](len).asInstanceOf[Array[T]]
/* snip */
case _ => java.lang.reflect.Array.newInstance(runtimeClass, len).asInstanceOf[Array[T]]
}
And then your type:
scala> classTag[Int with String with Double].runtimeClass
res4: Class[_] = int
It seems pretty clear how it's arriving at the conclusion to use the first type. The runtimeClass of Int with String with Double is Int, and the newArray method uses the runtimeClass to construct the new Array. So the Array is filled with default Int values. Likewise for the other order combinations.
Why is the runtime class Int? Well, Int with String with Double isn't an actual class, but Int is. The compiler's choice of which class to use can't just be arbitrary, so why not the first?
Can a compound type be instanced explicitly?
I'm not sure what you mean by this. If you think about it, the compiler kind of has to favor one type in this composition. What would an explicit Int with String with Double look like? What about Int with String with Double with Product with Process ? I don't know, either.
Each of the array elements has access to the methods of the three types: Int, String and Double
They do, and yet they don't.
scala> val arr = classTag[Int with Process].newArray(3)
arr: Array[Int with Process] = Array(0, 0, 0)
scala> arr(0).exitValue()
java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.Process
You're really just tricking the compiler into believing you have an Array of these types, when in fact you don't (and can't, because nothing can be a sub-type of both Int and Process).
Their use case is only for when the types composing the compound are related through inheritance and so on?
Pretty much, yes. I can't think if any situation in which you'd ever want to try to build these types directly. Their main use case is to guarantee that a type inherits from other specific types.
For example, a method that requires that a parameter inherit methods from two traits:
trait Hello { def hello = println("Hello") }
trait Bye { def bye = println("Bye") }
def greet(hb: Hello with Bye): Unit = { hb.hello; hb.bye }
class A extends Hello
class B extends Hello with Bye
scala> greet(new A)
<console>:15: error: type mismatch;
found : A
required: Hello with Bye
greet(new A)
^
scala> greet(new B)
Hello
Bye

Scala - simple design by contract

I'm learning Scala as a personal project as I'm fed up with the verbosity of Java. I like a lot of what I see, but wonder if there's a way to efficiently implement some simple contracts on methods. I'm not (necessarily) after full DbC, but is there a way to: -
indicate that a parameter or a class field is REQUIRED, i.e. CANNOT be null. The Option thing seems to indicate cleanly if an OPTIONAL value is present, but I want to specify class invariants (x is required) and also to succinctly specify that a parameter is required. I know I can do "if's" throwing some kind of exception, but I want a language feature for this VERY common use-case. I like my interfaces tight, I dislike defensive programming.
Is it possible to define succinct and efficient (runtime performance) ranged types, such as "NonNegativeInt" - I want to say that a parameter is >= 0. Or within a range. PASCAL had these types and I found them excellent for communicating intent. That is one of the big drawbacks of C, C++, Java, etc. When I say succinct I mean I want to declare a variable of this type as easily as a normal int, not having to new each and every instance on the heap.
For point (1), Option should indeed be enough. This is because while scala supports null values, it does so mainly for compatibility with Java. Scala code should not contain null, values, and where it does it should be constrained to very localized places, and converted to an option as soon as possible (good scala code will never let null values propagate).
So in idiomatic scala, if a field or parameter is not of type Option this really means that it is required.
Now, there is also the (experimental and never fully supported as far as I can tell) NotNull trait. See How does the NotNull trait work in 2.8 and does anyone actually use it?
For point (2) scala 2.10 introduces value classes. With them, you could define your very own class that wraps Int without runtime overhead, and implement its operators as you see fit. The only places where you would have a runtime check would be when converting from a normal Int to your NonNegativeInt (throw an exception if the int is negative). Note that this check would be performed everytime you create a new NonNegativeInt, which also means everytime you perform an operation, so there would be a non-null runtime impact. But Pascal was in the very same situation (range checks are performed at runtime in Pascal) so I guess that you're OK with this.
UPDATE: Here is an example implementation of NonNegativeInt (here renamed to UInt):
object UInt {
def apply( i: Int ): UInt = {
require( i >= 0 )
new UInt( i )
}
}
class UInt private ( val i: Int ) extends AnyVal {
override def toString = i.toString
def +( other: UInt ) = UInt( i + other.i)
def -( other: UInt ) = UInt( i - other.i)
def *( other: UInt ) = UInt( i * other.i)
def /( other: UInt ) = UInt( i / other.i)
def <( other: UInt ) = i < other.i
// ... and so on
}
and some example usage in the REPL:
scala> UInt(123)
res40: UInt = 123
scala> UInt(123) * UInt(2)
res41: UInt = 246
scala> UInt(5) - UInt(8)
java.lang.IllegalArgumentException: requirement failed
at scala.Predef$.require(Predef.scala:221)
at UInt$.apply(<console>:15)
...
What is this null of which you speak?
Seriously, bar null at the borders of your system, where it comes into contact with code you did not write. At that boundary you make sure all nullable values are converted to Option.
Likewise, don't use exceptions. As with null, bar them at the gate. Turn them into Either or use ScalaZ Validation.
As for dependent types (where the type interacts with or depends on specific values or subsets of values such as the natural numbers) it's more work. However, Spire has a Natural type. It might not be exactly what you want since it's arbitrary precision but it does impose the non-negative aspect of the natural numbers.
Addendum
Conversion from a nullable value to Option is trivially accommodated by the Scala Standard Library itself in the form of the Option factroy. To wit:
scala> val s1 = "Stringy goodness"
s1: String = Stringy goodness
scala> val s2: String = null
s2: String = null
scala> val os1 = Option(s1)
os1: Option[String] = Some(Stringy goodness)
scala> val os2 = Option(s2)
os2: Option[String] = None
The Scala standard library comes built-in with exactly these kinds of assertion mechanisms: the assert, assume, required, and ensuring methods. The latter two especially allow you to write preconditions and postconditions in a Design-By-Contract style. Simple example of natural number division:
def divide(x: Int, y: Int): Int = {
require(x > y, s"$x > $y")
require(y > 0, s"$y > 0")
x / y
} ensuring (_ * y == x)
The require calls throw an IllegalArgumentException if the requirements are not met, and show the interpolated string as the exception's message. The ensuring call throws an exception if the given condition doesn't hold.
More details at: https://madusudanan.com/blog/scala-tutorials-part-29-design-by-contract/
There's also a tool that does formal verification on a subset of Scala written in this style: https://github.com/epfl-lara/stainless