I should create class Example[T] with 2 different implementations:
If T can be converted to Numeric
Another case
I tried to do this with implicit conversion
class ExampleImplicits{
implicit def convert[T](example: Example[T]): ExampleSecond[T] = new ExampleSecond[T]()
}
class Example[T:Numeric]...
class ExampleSecond[T]...
I thought that if compiler will not find implicit conversion in scala.Numeric.Implicit for T, then he will raise my implicit conversion.
But as I tested code, this works not like this. How can I do this specialization?
UPDATE
What I want to get:
val x = new Example[Int]()
x.methodThatHaveOnlyNumerics()
x.methodThatHaveAllImplementations()
val y = new Example[String]()
y.methodThatHaveAllImplementations()
Now I can't compile my code.
Just create an implicit class that provides the additional methods in the case that the type parameter is Numeric:
class Example[X] {
def methodThatHaveAllImplementations(): Unit = println("all")
}
implicit class ExampleNumOps[N: Numeric](ex: Example[N]) {
def methodThatHaveOnlyNumerics(): Unit = println("num")
}
val x = new Example[Int]()
x.methodThatHaveOnlyNumerics()
x.methodThatHaveAllImplementations()
val y = new Example[String]()
y.methodThatHaveAllImplementations()
Output:
num
all
all
I tested this code. And it seems code working as expected. Here object ob returns ExampleSecond[Int]. I tested with below code.
I hope this is what you expecting.
object HelloWorld {
def main(args: Array[String]): Unit = {
val ex = new Example[Int]
val x = new ExampleImplicits
val ob = x.convert(ex) // passing Example[Int] object to convert
println(ob.isInstanceOf[ExampleSecond[Int]]) // returns true because it is of ExaampleSecond[Int] object.
}
}
class ExampleImplicits {
implicit def convert[T](example: Example[T]): ExampleSecond[T] = new ExampleSecond[T]()
}
class Example[T: Numeric] {
println("ex")
}
class ExampleSecond[T] {
println("ex2")
}
Output :
ex
ex2
true
An alternative to Andrey's answer:
class Example[T] {
def methodThatHaveOnlyNumerics()(implicit num: Numeric[T]) = ...
def methodThatHaveAllImplementations() = ...
}
Related
I want to bind a check method to the Test in such a way that the implementation does not contain an argument (look at the last line). It is necessary to use type classes here, but I'm new in Scala, so I have problems.
Object Checker is my attempts to solve the problem. Perhaps it is enough to make changes to it...
trait Test[+T] extends Iterable[T]
class TestIterable[+T](iterable: Iterable[T]) extends Test[T] {
override def iterator: Iterator[T] = iterable.iterator
}
object Test {
def apply[T](iterable: Iterable[T]): Test[T] = new TestIterable[T](iterable)
}
trait Check[M] {
def check(m: M): M
}
object Checker {
def apply[M](implicit instance: Check[M]): Check[M] = instance
implicit def checkSyntax[M: Check](m: M): CheckOps[M] = new CheckOps[M](m)
private implicit def test[T](m: Test[T]) : Check[Test[T]] = {
new Check[Test[T]] {
override def check(m: Test[T]) = m
}
}
final class CheckOps[M: Check](m: M) {
def x2: M = Checker[M].check(m)
}
}
import Checker._
val test123 = Test(Seq(1, 2, 3))
Test(test123).check
Scala 2.10:
class A(val x:Int=0) {
}
object A {
def apply(x:Int): A = new A(x) // works
def apply(): A = new A() // fails to compile
}
val b = A(123) // :-)
val a = A() // >-(
Solution?
Even though your code should work (I suspect some implicit argument being at work here)
you can simplify it by doing
object A {
def apply(x: Int=0): A = New A(x)
}
while being shorter there's the drawback of being less DRY
I am new to Scala and dont know why i have to do an (unintuitive for me) type cast related to path dependent types in the following code.
(I don't like getters, setters nor nulls, they are here to separate operations and disambiguate the source of errors)
// Module A public API
class ModA {
trait A
}
// Module B public API that depends on types defined in Module A
class ModB(val modA: ModA) {
trait B {
def getA: modA.A;
def setA(anA: modA.A);
}
}
// One implementation of Module A
class ModAImpl extends ModA {
class AImpl extends A
}
// One implementation of Module B
class ModBImpl(mod: ModA) extends ModB(mod) {
class BImpl extends B {
private[this] var privA: modA.A = _;
override def getA = privA;
override def setA(anA: modA.A) = privA = anA;
}
}
object Main {
def main(args: Array[String]): Unit = {
// wiring the modules
val modAImpl = new ModAImpl;
val modBImpl = new ModBImpl(modAImpl);
// wiring objects
val a = new modAImpl.AImpl;
val b = new modBImpl.BImpl;
b.setA(a); //don't compile and complain: type mismatch; found: modAImpl.A required: modBImpl.modA.A
//i have to do this horrible and coutnerintuitive cast to workaround it
b.setA(a.asInstanceOf[modBImpl.modA.A]);
var someA: modAImpl.A = null;
someA = b.getA; // don't compile with same reason
someA = b.getA.asInstanceOf[modAImpl.A]; // horrible cast to workaround
println(a == b.getA); // however this prints true
println(a eq b.getA); // this prints true too
}
}
I have read about singleton types to inform the compiler when two types are the same, but I don't know how to apply this here.
Thanks in advance.
You can stick a type parameter on the ModB types:
class ModA { trait A }
class ModB[AA](val modA: ModA { type A = AA }) {
trait B {
def getA: AA
def setA(anA: AA)
}
}
class ModAImpl extends ModA { class AImpl extends A }
class ModBImpl[AA](
mod: ModA { type A = AA }) extends ModB(mod) {
class BImpl extends B {
private[this] var privA: AA = _
override def getA = privA
override def setA(anA: AA) = privA = anA
}
}
And the type inference all works out as desired:
scala> val modAImpl = new ModAImpl
modAImpl: ModAImpl = ModAImpl#7139edf6
scala> val modBImpl = new ModBImpl(modAImpl)
modBImpl: ModBImpl[modAImpl.A] = ModBImpl#1dd7b098
scala> val a = new modAImpl.AImpl
a: modAImpl.AImpl = ModAImpl$AImpl#4cbde97a
scala> val b = new modBImpl.BImpl
b: modBImpl.BImpl = ModBImpl$BImpl#63dfafd6
scala> b.setA(a)
Let's start by simplifying your code ridding out the unnecessary complexity.
class Aout {
class Ain
}
class Bout(val link: Aout) {
class Bin(val field: link.Ain)
}
object Main {
def main(args: Array[String]): Unit = {
// wiring outer object
val aout: Aout = new Aout;
val bout: Bout = new Bout(aout);
// wiring inner object
val ain: aout.Ain = new aout.Ain;
val bin: bout.Bin = new bout.Bin(ain); //don't compile and complain: type mismatch; found: aout.Ain required: bout.link.Ain
}
}
Answer:
The compiler complains with a type mismatch error because he compares the paths of the two declared types involved in the assignment, and they are different.
The compiler is not intelligent enough to notice that at that point aout eq bout.link. You have to tell him.
So, replacing the line
val ain: aout.Ain = new aout.Ain;
with
val ain: bout.link.Ain = new bout.link.Ain;
solves the path-dependent type mismatch.
Anyway, correcting the type's path in your original code is not enough because there is also an inheritance problem.
One solution to that is to make the class ModBImpl know the ModAImpl class like this:
class ModA {
trait A
}
class ModB[M <: ModA](val modA: M) { // type parameter added
trait B {
def getA: modA.A;
def setA(anA: modA.A);
}
}
class ModAImpl extends ModA {
class AImpl extends A
}
class ModBImpl(mod: ModAImpl) extends ModB(mod) { // changed type of `mod` parameter from `ModA` to `ModAImpl`
class BImpl extends B {
private[this] var privA: modA.A = _;
override def getA: modA.A = privA;
override def setA(anA: modA.A): Unit = privA = anA;
}
}
object Main {
def main(args: Array[String]): Unit = {
val modAImpl = new ModAImpl;
val modBImpl = new ModBImpl(modAImpl);
val a: modBImpl.modA.AImpl = new modBImpl.modA.AImpl; // changed the path of the type
val b: modBImpl.BImpl = new modBImpl.BImpl;
b.setA(a); // here IntellijIde complains with a type mismatch error, but the ScalaIDE (eclipse) and the scala compiler work fine.
}
}
If the rules of your business don't allow that the ModBImpl class has knowledge of the ModAImpl class, tell me so we can find another solution.
I have a simple enum like this:
object ConditionOperator extends Enumeration {
val Equal = Value("equal")
val NotEqual = Value("notEqual")
val GreaterOrEqual = Value("greaterOrEqual")
val Greater = Value("greater")
val LessOrEqual = Value("lessOrEqual")
val Less = Value("less")
And I'd like to add a method to each enum so that I can use it like this:
def buildSqlCondition(field: String, operator: ConditionOperator.Value, value: String ) = {
val sqlOperator = operator.toSql
[...]
So, ConditionOperator.Equal.toSql wuld return "=", and ConditionOperator.NotEqual.toSql would return "<>", etc...
But I don't know how to define a toSql method, so that each enum can "see" it's own value and decide how to translate itself to a sql operator...
This is an example of what I have found for Scala 2.9.2 from various searches on the topic in the past:
object Progress extends Enumeration {
type enum = Value
val READY = new ProgressVal {
val isActive = false
def myMethod: Any = { .. }
}
val EXECUTE = new ProgressVal {
val isActive = true
def myMethod: Any = { .. }
}
val COMPLETE = new ProgressVal {
val isActive = false
def myMethod: Any = { .. }
}
protected abstract class ProgressVal extends Val() {
val isActive: Boolean
def myMethod: Any
}
implicit def valueToProgress(valu: Value) = valu.asInstanceOf[ProgressVal]
}
type Progress = Progress.enum
The implicit is key to making this usable.
The type enum and type Progress are somewhat redundant; I include them to present both concepts as something I've found helpful.
To give credit where it's due, the original idea for this came from Sean Ross in a response to a question of which this one is a duplicate.
You can start by defining an inner class that overrides Enumeration.Val. To simplify things, let's call it Value (we overload the original meaning of Value as defined in Enumeration).
So we have our new Value type which inherits Enumeration.Val which itself inherits Enumeration.Value.
Given that toSql has no side effects and returns a different string for each enumeration, you might as well just make it a val.
Finally, to make it fully usable, you'll want to have ConditionOperator.apply and ConditionOperator.withName to return your newly defined Value class instead of the Value type as defined in Enumeration.
Otherwise, when using apply or withName to look up an instance of ConditionOperator by index/name, you won't be able to call toSql because the enumeration type will not be specific enoough.
Ideally we'd like to just override apply and withName and add a cast to ConditionOperator.Value, but these methods are final.
However we can employ a small trick here: define new methods apply and withName with the same signature but an additional implicit parameter that will always be available (Predef.DummyImplicit fits this rolle perfectly).
The additional parameter ensures that the signature is different so that we are able to define these new methods, while at the same time being nearly indistinguishable from the original apply/withName methods.
The rules for overloading resolution in scala ensure that our new methods are the ones favored by the compiler (so we have in practice shadowed the original methods).
object ConditionOperator extends Enumeration {
// Here we overload the meaning of "Value" to suit our needs
class Value(name: String, val toSql: String) extends super.Val(name) {
def someFlag: Boolean = true // An example of another method, that you can override below
}
val Equal = new Value("equal", "=")
val NotEqual = new Value("notEqual", "<>")
val GreaterOrEqual = new Value("greaterOrEqual", ">=")
val Greater = new Value("greater", ">")
val LessOrEqual = new Value("lessOrEqual", "<=") { override def someFlag = false }
val Less = new Value("less", "<")
final def apply(x: Int)( implicit dummy: DummyImplicit ): Value = super.apply(x).asInstanceOf[Value]
final def withName(s: String)( implicit dummy: DummyImplicit ): Value = super.withName(s).asInstanceOf[Value]
}
You can check that you can now do things like ConditionOperator(2).toSql or ConditionOperator.withName("greaterOrEqual"), which both return ">=" as expected.
Finally, the above gymnastic can be abstracted away:
abstract class CustomEnumeration extends Enumeration {
type BaseValue = super.Val
type CustomValue <: super.Value
type Value = CustomValue
final def apply(x: Int)( implicit dummy: DummyImplicit ): CustomValue = super.apply(x).asInstanceOf[CustomValue]
final def withName(s: String)( implicit dummy: DummyImplicit ): CustomValue = super.withName(s).asInstanceOf[CustomValue]
}
object ConditionOperator extends CustomEnumeration {
class CustomValue(name: String, val toSql: String) extends BaseValue(name) {
def someFlag: Boolean = true
}
val Equal = new Value("equal", "=")
val NotEqual = new Value("notEqual", "<>")
val GreaterOrEqual = new Value("greaterOrEqual", ">=")
val Greater = new Value("greater", ">")
val LessOrEqual = new Value("lessOrEqual", "<=") { override def someFlag = false }
val Less = new Value("less", "<")
}
object ConditionOperator extends Enumeration {
implicit def overrideValue(v:Value) = new OverridedValue(v)
class OverridedValue(val v:Value) {
def toSql = v.toString
}
val Equal = Value("=")
val NotEqual = Value("<>")
val GreaterOrEqual = Value(">=")
val Greater = Value(">")
val LessOrEqual = Value("<=")
val Less = Value("<")
}
import ConditionOperator._
assert(Equal.toSql == "=")
And in scala 2.10, you can make it simpler by using implicit class, replace
implicit def overrideValue(v:Value) = new OverridedValue(v)
class OverridedValue(val v:Value) {
def toSql = v.toString
}
with
implicit class OverridedValue(val v:Value) {
def toSql = v.toString
}
I have a problem with specifying types for enumeration values (instances of scala.Enumeration) in functions. This originally arises from my need to serialize enumeration objects in database, but I've extracted the problematic code in the following example:
object EnumerationTypes {
class EnumerationProcessor[E <: Enumeration](enum: E, value: E#Value) {
def process: E#Value = {
value
}
}
object Enum extends Enumeration {
type EnumValue = Value
val a = Value(1, "a")
val b = Value(2, "b")
}
case class Obj(val flag: Enum.EnumValue)
def main(args: Array[String]) {
val processor = new EnumerationProcessor(Enum, Enum.a)
val obj = Obj(processor.process)
}
}
It leads to the following compilation error:
error: type mismatch;
found : EnumerationTypes.Enum#Value
required: EnumerationTypes.Enum.EnumValue
val obj = Obj(processor.process)
While this works ok:
object EnumerationTypesOk {
class EnumerationProcessor[E <: Enumeration](enum: E, value: E#Value) {
def process: E#Value = {
value
}
}
class Enum extends Enumeration {
type EnumValue = Value
val a = Value(1, "a")
val b = Value(2, "b")
}
object Enum extends Enum
case class Obj(val flag: Enum#EnumValue)
def main(args: Array[String]) {
val processor = new EnumerationProcessor(Enum, Enum.a)
val obj = Obj(processor.process)
}
}
But I don't want my code to be looks like this (first define class and then its singleton instance).
So the problem: how I can make value type be exactly the enum.EnumValue? While it seems impossible, because types cannot depend on concrete values, maybe there are some tricks to achieve desired effect with no additional boilerplate.
Edit:
Looks like you just need to help the type inferencer a bit to get your first solution working:
val processor = new EnumerationProcessor[Enum.type](Enum, Enum.a)
Hopefully someone smarter than I am will come along and explain why.
Before the OP's clarifying comment:
object EnumerationTypes {
class EnumerationProcessor[E <: Enumeration, V <: E#Value](enum: E, value: V) {
def process: V = {
value
}
}
object Enum extends Enumeration {
type EnumValue = Value
val a = Value(1, "a")
val b = Value(2, "b")
}
case class Obj(val flag: Enum.EnumValue)
def main(args: Array[String]) {
val processor = new EnumerationProcessor(Enum, Enum.a)
val obj = Obj(processor.process)
}
}
Another potential solution is to define a mixin that allows you to create a 'processor' for a particular Enumeration instance:
object EnumerationTypes {
trait EnumerationProcessor { self: Enumeration =>
def processor(value: self.Value): () => self.Value = () => {
value
}
}
object Enum extends Enumeration with EnumerationProcessor {
type EnumValue = Value
val a = Value(1, "a")
val b = Value(2, "b")
}
case class Obj(val flag: Enum.EnumValue)
def main(args: Array[String]) {
val processor = Enum.processor(Enum.a)
val obj = Obj(processor())
}
}