I am beginner in scala. Got a doubt while trying to implement Collections..
class MyLinkedHashMap[K, V] {
var initialCapacity = 16
private var index = 0
var map: Array[Node[K, V]]
var head: Node[K, V]
var tail: Node[K, V]
class Node[K, V] {
var key: K;
var value: V;
var next: Node[K, V]
var before: Node[K, V]
var after: Node[K, V]
def Node(key: K, value: V, next: Node[K, V]) {
this.key = key
this.value = value
this.next = next
}
}
def MyLinkedHashMap() {
map = new Array[Node[K, V]](initialCapacity)
}
def MyLinkedHashMap(initialCapacity: Int) {
if (initialCapacity < 0) {
throw new IllegalArgumentException();
}
map = Array[Node[K, V]](initialCapacity)
}
private def hash(key:K): Int = {
return Math.abs(key.hashCode()) % initialCapacity
}
def put(key: K, value: V): Unit = {
if (key == null) {
return;
}
var hashIndex = hash(key)
val newNode = new Node[K, V](key, value, null)
}
}
The error I get at Line no: 42 is
Too many arguments for constructor Node
However if I declare class Node in the object of MyLinkedHashMap I do not get this error. I wanted to know the reason for this error.
And I didn't want the Node class to be abstract, however the following error is raised when not declared abstract.
Class 'Node' must either be declared abstract or implement abstract member 'next: Node[K, V]' in 'MyLinkedHashMap.Node'
Why is it neccessary for Node class to be abstract?
The error I get at Line no: 42 is
Too many arguments for constructor Node
Here, you are calling Node's constructor with three arguments:
new Node[K, V](key, value, null)
But here you define the Node class's primary constructor with no parameter list:
class Node[K, V]
And there is no auxiliary constructor defined either.
So, the only constructor that exists on Node is the one that takes no parameters but you are calling it with three arguments.
If you want to call a constructor with three arguments, you need to define a constructor (probably the primary constructor) which takes three parameters, maybe something like this:
class Node[K, V](var key: K, var value: V, var next: Node[K, V])
Related
How do I create a covariant data structure containing numeric data types?
In scala I can create a covariant data structure, with a hierarchy of type parameters:
abstract class Car[+T] {
def value: T
}
class RaceCar extends Car[RacingWheel] {
def value: RacingWheel = new RacingWheel
}
class NormalCar extends Car[BoringWheel] {
def value: BoringWheel = new BoringWheel
}
class Wheel
case class RacingWheel() extends Wheel
case class BoringWheel() extends Wheel
object Car {
def main(args: Array[String]): Unit = {
val rCar: Car[Wheel] = new RaceCar
val nCar: Car[Wheel] = new NormalCar
val listCars: List[Car[Wheel]] = List(rCar, nCar)
}
}
However, when I replace the Wheel's with numeric data types I run into a problem, because the numeric data types do not have a common type parent other than AnyVal:
abstract class Item[+N] {
def value: N
}
class IntItem(x : Int) extends Item[Int] {
override def value: Int = x
}
class DoubleItem(x : Double) extends Item[Double] {
override def value: Double = x
}
object Item {
def main(args: Array[String]): Unit = {
// ERROR Expression of IntItem does not conform to expected type Item[Number]
val iItem: Item[Number] = new IntItem(10)
// ERROR Expression of DoubleItem does not conform to expected type Item[Number]
val dItem: Item[Number] = new DoubleItem(10.9)
val l: List[Item[Number]] = List(iItem, dItem)
// ERROR: Expression of IntItem does not conform to expected type Item[Double]
val iItem2: Item[Double] = new IntItem(10)
val dItem2: Item[Double] = new DoubleItem(10.9)
val l2: List[Item[Double]] = List(iItem2, dItem2)
}
}
Outside of the covariant data structure I get mixed results:
object NumberMain {
val a : Int = 5
val b : Double = 10.0
val list : List[Number] = List(a, b)
// works, so Number must be related to Int and Double, right?
val x : Number = 5
// ERROR: Expression of type Number doesn't conform to expected type Int
val y : Int = x
// does not work, so Number is not related to Int and Double after all...
}
What changes do I have to make to the Item data structure? Can I tell it that all items can be seen as of type numeric?
In Scala, Int and Double do not share hierarchy with a common Number class. The Typeclass pattern can help you in these cases to define extra features for types without a common supertype.
trait MyNumber[A]
implicit case object IntMyNumber extends MyNumber[Int]
implicit case object DoubleMyNumber extends MyNumber[Double]
class Item[N](x: N)(implicit n: MyNumber[N]) {
def value: N = x
}
The Item class constructor now expects a second group of parameters labeled with the implicit keyword. If you call the method without this group of parameters, the compiler tries to find it (an instance of MyNumber) from variables or imports also labeled with implicit (Where does Scala look for implicits?).
We're just defining here that Int and Double implements MyNumber, but it doesn't do anything. We can write then the class as:
class Item[N : MyNumber](x: N) {
def value: N = x
}
And it works as we expected:
val iItem = new Item(1)
val dItem = new Item(1.0)
scala> iItem.value
res1: Int = 1
scala> dItem.value
res2: Double = 1.0
If we try to build an item of anything without an instance of MyNumber, the compiler throws an error:
val sItem = new Item("S")
error: could not find implicit value for evidence parameter of type MyNumber[String]
If you want MyNumber to be any numeric, Scala implements a Numeric typeclass.
Edit
If you want to add some features to the typeclass that are different for each number, you can do:
trait MyNumber[A] {
def doStuff(a: A): Unit
}
implicit case object IntMyNumber extends MyNumber[Int] {
def doStuff(number: Int): Unit = println("Int")
}
implicit case object DoubleMyNumber extends MyNumber[Double] {
def doStuff(number: Double): Unit = println("Double")
}
case class Item[+N](x: N)(implicit myNumber: MyNumber[N]) {
def value: N = x
def doStuff = myNumber.doStuff(x)
}
I have an abstract class that will be implemented in many different ways. I am trying to create a method that can take any one of these implementors as a parameter, and return a new instance of the same type. I am trying to implement this behavior by passing a "factory" function to the method that yields a new object of an abstract type (which will be set appropriately in each implementor).
I've tried to breakdown the problem I'm having into the following code:
My parent abstract class:
abstract class Parent(val x: Int) {
type Self <: Parent
def factory: Int ⇒ Self
def me = "Parent"
}
An example of a Child class:
class Child(x: Int) extends Parent(x) {
type Self = Child
override def factory: Int ⇒ Self = {
(v: Int) ⇒ new Child(v)
}
override def me = "Child"
}
I'm trying to use the Self type parameter as a way to ensure that the factory method generates an object of the correct type.
Now the method itself:
object Parent {
def transform[T <: Parent](input: T#Self, factory: (Int ⇒ T#Self)): T#Self = {
//do stuff with input
input.me
val result = 123
factory(result)
}
}
Now when I try to actually wire this all up:
class Transformer[T <: Parent] {
var everyone: List[T#Self] = List.empty
def start() = {
val updated = for (e ← everyone) yield {
Parent.transform[T](e, e.factory)
}
everyone = updated
}
}
I get a compile error when I try to pass the factory to the transform method
Type mismatch, expected (Int) => T#Self, actual (Int) => Parent.this.Self
I've tried a variety of things to get this to work, but no luck. I'm very new to this still, so it's possible (probably likely) I'm trying to do something crazy here. A better alternative would be greatly appreciated, but I'm still interested to see if it's possible to get something like this to work. The end goal is to have a way for the transform method to generate new instances of the exact same type that was provided as a parameter.
Any help is greatly appreciated. Thanks!
I'm trying to use the Self type parameter as a way to ensure that the
factory method generates an object of the correct type.
This reminds me of tpolecat's Returning the "Current" Type in Scala:
I have a type hierarchy … how do I declare a supertype method that returns the “current” type?
We can adapt the F-Bounded Types approach discussed in that post to your Parent and Child hierarchy:
trait Parent[A <: Parent[A]] { this: A =>
def x: Int
def factory: Int ⇒ A
def me = "Parent"
}
class Child(override val x: Int) extends Parent[Child] {
override def factory = (v: Int) ⇒ new Child(v)
override def me = "Child"
}
class OtherChild(override val x: Int) extends Parent[OtherChild] {
override def factory = (v: Int) ⇒ new OtherChild(v)
override def me = "OtherChild"
}
object Parent {
def transform[A <: Parent[A]](input: A): A = {
//do stuff with input
input.me
val result = 123
input.factory(result)
}
}
And then, following the Bonus Round: How do we deal with collections? section, your Transformer becomes something like this:
class Transformer {
import scala.language.existentials
var everyone = List[A forSome { type A <: Parent[A] }](new Child(1), new OtherChild(2))
def start() = {
val updated = everyone.map(Parent.transform(_))
everyone = updated
}
}
I am defining an abstract class taking a type parameter, along with several concrete classes which set this type.
abstract class GenericFoo[T: ClassTag] {
def defaultValue: T
def useTheValue(v: T): T
}
object DoubleFoo extends GenericFoo[Double] {
def defaultValue = 42.0
def useTheValue(v: Double) = v * 2
}
object IntFoo extends GenericFoo[Int] {
def defaultValue = 1337
def useTheValue(v: Int) = v + 64
}
But when storing my Foos in a mixed collection, it seems that my type parameter T always ends up being inferred up to Any.
val fooCollection:List[GenericFoo[_]] = List(DoubleFoo, IntFoo)
for {
foo <- fooCollection
defaultValue = foo.defaultValue
result = foo.useTheValue(defaultValue)
// Error: `defaultValue` has type `Any`, cannot call `useTheValue`
} yield result
Based on several answers to similar questions, I thought using type parameter wildcard (GenericFoo[_]), and maybe ClassTag would help keep type information, but I couldn't get this example to work as I wanted.
In the snippet above, I would want foo.defaultValue to be recognized as having the correct type (T) to be applicable in foo.useTheValue(). Have I missed something?
Edit: #gzm0 was prompt to suggest that I use abstract type members. My original use-case was a little more involved, as I am also defining an abstract type for a companion object. My actual code does something similar to:
trait GenericCompanion[T] {
// Some "static" members
def defaultValue: T
def useTheValue(v: T): T
}
abstract class GenericFoo[T] {
def getCompanion: GenericCompanion[T]
// Because of this operation, it's important that we have the same type `T`
def useCompanion: T = getCompanion.useTheValue(theActualValue)
val theActualValue: T
}
object ConcreteCompanion[Double] extends GenericCompanion[Double] {
// ...
}
object ConcreteFoo[Double] extends GenericFoo[Double] {
def getCompanion = ConcreteCompanion
}
Each concrete implementation of GenericFoo[T] also comes with a CompanionFoo[T]. Concrete sub-classes of GenericFoo are supposed to instantiated, while CompanionFoo[T] objects are here to hold "static" properties and operations. In this context, it is very important that the type parameter in GenericFoo is the same as the type parameter in GenericCompanion.
(I hope this is clear enough, sorry if my example is convoluted!)
This is a vanilla example for abstract type members. Try this:
abstract class GenericFoo {
type V
def defaultValue: V
def useTheValue(v: V): V
}
object DoubleFoo extends GenericFoo {
type V = Double
def defaultValue = 42.0
def useTheValue(v: Double) = v * 2
}
object IntFoo extends GenericFoo {
type V = Int
def defaultValue = 1337
def useTheValue(v: Int) = v + 64
}
val fooCollection:List[GenericFoo] = List(DoubleFoo, IntFoo)
Rest of the code remains unchanged.
If you use an abstract type member (rather than a type parameter), Scala will take track of the concrete types it knows for a given value.
From your example explained:
val foo: GenericCollection = ???
val defaultValue = foo.defaultValue
// defaultValue: foo.V
foo.useTheValue(defaultValue)
// foo.useTheValue: (foo.V): foo.V
Although the compiler does not know what true type foo.V is, it can nevertheless figure out that the type signatures match and that using calling useTheValue with defaultValue is OK.
As far as I can tell, this would also be a perfectly OK reasoning with type parameters, Scala just does not do it.
UPDATE
You can still do this, even with the more involved example:
trait GenericCompanion {
type T
// Some "static" members
def defaultValue: T
def useTheValue(v: T): T
}
abstract class GenericFoo { self =>
type T
def getCompanion: GenericCompanion { type T = self.T }
// Because of this operation, it's important that we have the same type `T`
def useCompanion: T = getCompanion.useTheValue(theActualValue)
val theActualValue: T
}
And the concrete implementations:
object ConcreteCompanionDouble extends GenericCompanion {
type T = Double
def defaultValue: Double = ???
def useTheValue(v: Double): Double = ???
// ...
}
object ConcreteFooDouble extends GenericFoo {
type T = Double
def getCompanion = ConcreteCompanionDouble
val theActualValue: Double = ???
}
i have a class that takes an implicit parameter which is used by functions called inside class methods. i want to be able to either override that implicit parameter and have both the class and its inherited parent class have a reference to the same new implicit object.
making the Parent implicit a var and setting that to a new value successfully overrides the implicit in the parent, but not the child.
(this is similar to scala: override implicit parameter to constructor, except there is the added restriction that the override affect both child class and parent class.)
for example:
def outside(implicit x: Boolean) {
println(x)
}
class Parent(implicit var x: Boolean) {
def setImplicit() {
x = true
}
def callOutside {
outside
}
}
class Child(implicit x: Boolean) extends Parent {
override def callOutside {
outside
}
}
and then:
scala> val a = new Parent()(false)
a: Parent = Parent#c351f6d
scala> a.callOutside
false
scala> a.setImplicit()
scala> a.callOutside
true // <-- sees the new implicit correctly
scala> val b = new Child()(false)
b: Child = Child#68331dd0
scala> b.callOutside
false
scala> b.setImplicit()
scala> b.callOutside
false // <-- wrong, desire "true" instead
is there any way to get the desired behavior? doing things like making both Parent and Child implicit be a var doesn't seem to work. thanks!
You could just
class Parent(x0: Boolean) {
implicit var x = x0
...
}
if you didn't really need the class parameter to be implicit. I'll assume that you do.
One alternative is to put the implicits on the companion object. Like so:
class Parent(x0: Boolean) {
implicit var x = x0
def setImplicit { x = true }
def outsideCall { outside }
}
object Parent {
def apply(implicit x: Boolean) = new Parent(x)
}
class Child(x0: Boolean) extends Parent(x0) {
def callOutside { outside }
}
object Child {
def apply(implicit x: Boolean) = new Child(x)
}
Alternatively, you could create a private main constructor for Child (decorated in some way so it's not ambiguous with the implicit) and use an implicit on a secondary constructor:
class Child private (b: Boolean, u: Unit) extends Parent()(b) {
def this()(implicit x: Boolean) = this(x,())
def callOutside { outside }
}
I'm trying to define a generic residue class ring in Scala. A residue class ring is defined by some base ring (e.g. the integers) and a modulus (e.g. two), which is a value from the base ring. Both rings and their elements are objects, hence the type of the modulus would normally be a dependent type, depending on the base ring. I understand this isn't allowed in Scala (for good reasons), so I'm trying to emulate it by approximating the type and doing a runtime check when the residue class ring is constructed.
The definition of ResidueClassRing is accepted without error, however, Scala doesn't let me instantiate it, for the argument two I get the error message
type mismatch;
found : dependenttypetest.DependentTypeTest.two.type
(with underlying type dependenttypetest.Integers.Integer)
required: dependenttypetest.EuclideanRing#E
Am I doing something wrong? Could this be a bug in the Scala type checker? Is there a better way to define ResidueClassRing?
This is with Scala 2.8.0 in the Eclipse IDE for Helios. The problem already occurred for 2.7.x. Here is a simplified version of the code:
package dependenttypetest
class EuclideanRing
{
thisRing =>
type E <: EuclideanRingElement;
def one: E;
trait EuclideanRingElement
{
def ring = thisRing;
def +(b: E): E;
def %(b: E): E;
}
}
object Integers extends EuclideanRing
{
type E = Integer;
val one: Integer = new Integer(1);
class Integer(n: Int) extends EuclideanRingElement
{
val intValue: Int = n;
def +(b: Integer): Integer = new Integer(intValue + b.intValue);
def %(b: Integer): Integer = new Integer(intValue % b.intValue);
}
}
class ResidueClassRing (val baseRing : EuclideanRing, m : EuclideanRing#E)
{
val modulus: baseRing.E =
m match {
case e: baseRing.E if m.ring == baseRing => e;
case _ => throw new IllegalArgumentException("modulus not from base ring");
};
type E = ResidueClassRingElement;
def one: E = new ResidueClassRingElement(baseRing.one);
class ResidueClassRingElement (e : baseRing.E)
{
def representative: baseRing.E = e % modulus;
def +(b: E) = new ResidueClassRingElement(
this.representative + b.representative);
}
}
object DependentTypeTest extends Application
{
val two = new Integers.Integer(2);
val mod2ring = new ResidueClassRing(Integers, two);
println(mod2ring.one + mod2ring.one);
}
This seems to work, but I couldn't get rid of the cast when calculating representative:
package dependenttypetest
abstract class EuclideanRing{
thisRing =>
type E <: EuclideanRingElement;
def one: E;
trait EuclideanRingElement
{
def ring = thisRing;
def +(b: E): E;
def %(b: E): E;
}
}
class Integers extends EuclideanRing {
type E = Integer;
val one: Integer = new Integer(1);
class Integer(n: Int) extends EuclideanRingElement
{
val intValue: Int = n;
def +(b: Integer): Integer = new Integer(intValue + b.intValue);
def %(b: Integer): Integer = new Integer(intValue % b.intValue);
override def toString = "Int" + intValue
}
}
object Integers extends Integers
class ResidueClassRing[ER <: EuclideanRing] (modulus : ER#E) {
val baseRing = modulus.ring
type E = ResidueClassRingElement;
def one: E = new ResidueClassRingElement(baseRing.one);
class ResidueClassRingElement (e : baseRing.E)
{
def representative = e % modulus.asInstanceOf[baseRing.E];
def +(b: E) = new ResidueClassRingElement(
this.representative + b.representative);
override def toString = "RC(" + representative + ")"
}
}
object DependentTypeTest extends Application {
val two = new Integers.Integer(2);
val mod2ring = new ResidueClassRing[Integers](two)
println(mod2ring.one + mod2ring.one)
}
BTW: Be careful with the Application trait, it's rightfully deprecated.
UPDATE: Added IntRing to clarify changes in trait Ring
The problem seems to be that the type inferencer does not automatically pick the most specific type which is what you need in your case. In addition to that you cannot have a dependent type argument in the same parameter list as the defining type.
What you could to do is pull the instance that the type depends on in the outer scope (which is done in the Rings class) and to force the compiler to pick the most specific type when instantiating the Rings class:
trait Ring {
type Element <: EuclideanRingElement
def one: Element
// for convenience could be defined anywhere of course
lazy val rings: Rings[this.type] = new Rings[this.type](this)
trait EuclideanRingElement {
def +(e: Element): Element
def %(e: Element): Element
}
}
class Rings[R <: Ring](val base: R) {
class ResidueClassRing(m: base.Element) {
def one = new Element(base.one)
class Element(e: base.Element) {
def repr = e % m
def +(that: Element) = new Element(this.repr + that.repr)
}
}
}
object IntRing extends Ring {
val one = new Element(1)
class Element(val n: Int) extends EuclideanRingElement {
def +(that: Element) = new Element(this.n + that.n)
def %(that: Element) = new Element(this.n % that.n)
override def toString = n formatted "Int(%d)"
}
}
Now you can use it like this:
scala> import IntRing._
import IntRing._
scala> val two = new Element(2)
two: IntRing.Element = Int(2)
scala> val r2 = new rings.ResidueClassRing(two)
r2: IntRing.rings.ResidueClassRing = Rings$ResidueClassRing#4b5075f9