Scala : Method overloading and type inference - scala

I cannot understand why Scala is not able to infer an overloaded method's arguments :
object A {
implicit object SequenceMarker
implicit object IntMarker
def b(f: Int => Seq[Int])(implicit ev: SequenceMarker.type) = 0
def b(f: Int => Int)(implicit ev: IntMarker.type) = 0
def c() = { b(i => i + 1) } // this doesn't compile
}
When I try to compile this, I get the following error :
error: missing parameter type
def c() = { b(i => i + 1) }
I've made some investigation using javap and scala -print and figure out that the previous code cannot be compiled without specifying what i is :
object A {
...
def c() = { b((i: Int) => i + 1) }
}
Why is that so ? Is there any other way to overload a method while not specifying its argument's type during the call ?
Thank you in advance.
UPDATE
I've noticed using scala -print :
#SerialVersionUID(value = 0) final <synthetic> class anonfun$c$1 extends scala.runtime.AbstractFunction1$mcII$sp with Serializable {
final def apply(i: Int): Int = anonfun$c$1.this.apply$mcII$sp(i);
<specialized> def apply$mcII$sp(i: Int): Int = i.+(1);
final <bridge> <artifact> def apply(v1: Object): Object = scala.Int.box(anonfun$c$1.this.apply(scala.Int.unbox(v1)));
def <init>(): <$anon: Function1> = {
anonfun$c$1.super.<init>();
()
}
}
that the argument seems to be casted in some way:
scala.Int.box(anonfun$c$1.this.apply(scala.Int.unbox(v1)))
This line changes depending on the argument's type :
scala.Int.box(anonfun$c$1.this.apply(scala.Int.unbox(v1)));
...
scala.Int.box(anonfun$c$1.this.apply(v1.$asInstanceOf[String]()))
which would explain why the type is required. Here is the whole log :
package <empty> {
object A extends Object {
def b(f: Function1, ev: A$SequenceMarker.type): Int = 0;
def b(f: Function1, ev: A$IntMarker.type): Int = 0;
def c(): Int = A.this.b({
(new <$anon: Function1>(): Function1)
}, A$IntMarker);
def <init>(): A.type = {
A.super.<init>();
()
}
};
object A$SequenceMarker extends Object {
def <init>(): A$SequenceMarker.type = {
A$SequenceMarker.super.<init>();
()
}
};
object A$IntMarker extends Object {
def <init>(): A$IntMarker.type = {
A$IntMarker.super.<init>();
()
}
};
#SerialVersionUID(value = 0) final <synthetic> class anonfun$c$1 extends scala.runtime.AbstractFunction1$mcII$sp with Serializable {
final def apply(i: Int): Int = anonfun$c$1.this.apply$mcII$sp(i);
<specialized> def apply$mcII$sp(i: Int): Int = i.+(1);
final <bridge> <artifact> def apply(v1: Object): Object = scala.Int.box(anonfun$c$1.this.apply(scala.Int.unbox(v1)));
def <init>(): <$anon: Function1> = {
anonfun$c$1.super.<init>();
()
}
}
}
Therefore, what I want to achieve cannot be done in the way previously described. Any other idea ?
UPDATE 2
I've also tried :
def c() = { b(_ + 1) }
but I get another error
error: missing parameter type for expanded function ((x$1) => x$1.$plus(1))
def c() = { b(_ + 1) }
When I comment the first b(f: Int => Seq[Int]), it compiles well.

It's because for purposes of overload resolution, arguments are typed without an expected type, so there is no information about what function is expected.
http://www.scala-lang.org/files/archive/spec/2.11/06-expressions.html#overloading-resolution
The compiler doesn't care that the set of possible overloads includes only methods that take an Int.

Related

Generic types in Scala

I want to overloading constructor of abstract class with specific type. For example, I have:
abstract class Polinom(v: T)
So, when I create Polinom[String], I want to call constructor(String), for Int I want to call constructor(Int). If T != String and T != Int then I call constructor(T). In addition, for T == Int my object must have method add, for T == String - reverse, for T != String and T != Int object doesn't has this methods. How can I do that?
You can use evidence parameters for this:
class Polinom[T](v: T) {
def add(i: Int)(implicit ev: T <:< Int) = v + i
def reverse(implicit ev: T <:< String): String = ev(v).reverse
}
val x = new Polinom(50)
val y = new Polinom("hello")
val z = new Polinom(None)
println(x.add(3))
println(y.reverse)
//println(z.add(3)) <- Isn't allowed. Error: Cannot prove that None.type <:< Int
If you want specific constructors for Int and String and can't get enough of that implicit evidence, you can do this:
def this(i: Int)(implicit ev: Int =:= T) = this({
//do special int stuff here
println("I am in the special int constructor")
ev(i)
})
def this(s: String)(implicit ev: String =:= T) = this({
//do special string stuff here
println("I am in the special string constructor")
ev(s)
})
EDIT: Apparently, the above didn't work for the OP, although it seems to be working for me, but you can always make a companion object and overload the apply method, as the other answers suggested.
class Polinom[T] private(v: T)
object Polinom {
def apply(i: Int): Polinom[Int] = new Polinom(i)
def apply(s: String): Polinom[String] = new Polinom(s)
def apply[T](x: T): Polinom[T] = new Polinom(x)
}
val x = Polinom(50)
val y = Polinom("hello")
val z = Polinom(None)
println(x.add(3))
println(y.reverse)
//println(z.add(3)) <- Isn't allowed. Error: Cannot prove that None.type <:< Int
Link to Scastie (the demo's below)
<script src="https://scastie.scala-lang.org/j8fWjvVFS3CumCo3WbUgqQ.js"></script>
It would be better to model that as an ADT, something like:
sealed trait Polinom[T] {
def v: T
}
object Polinom {
final case class IntPolinom private[Polinom] (v: Int) extends Polinom[Int] {
def add(x: Int): IntPolinom =
this.copy(v = this.v + x)
}
final case class StrPolinom private[Polinom] (v: String) extends Polinom[String] {
def reverse: StrPolinom =
this.copy(v = this.v.reverse)
}
final case class GenericPolinom[T] private[Polinom] (v: T) extends Polinom[T]
def apply[T](v: Int): IntPolinom =
IntPolinom(v)
def apply[T](v: String): StrPolinom =
StrPolinom(v)
def apply[T](v: T): GenericPolinom[T] =
GenericPolinom(v)
}
abstract class Polinom[T](v: T)
object Polinom {
def apply(i: Int): Polinom[Int] = constructor(i)
def apply(s: String): Polinom[String] = constructor(s)
def apply[T](v: T): Polinom[T] = constructor(v)
}
Polinom(0)
Polinom("hello")
Polinom(None)
For examples of the add and reverse methods, see the other answers to this question.

Scala, override method on generic type

I am trying to build a DSL, one of the method on this DSL is parameterless and use a bounded generic type. Today I have to add a "feature" that will ideally use the same method name. However, because the only parameter is the generic one, I cannot override it with the usual way.
Is there a trick to allow the use of the same method for different generic types ?
My method looks like:
def ask[H <: Handler] = {
new CommandBuilder[H]
}
class CommandBuilder[H <: Handler] {
def toExecute[C <: H#C](command: C) = {
//...
}
}
And I would like to add:
def ask[S <: State] = {
new QueryBuilder[S]
}
class QueryBuilder[S <: State] {
def toExecute[Q <: S#Q](query: Q) = {
//...
}
}
I was thinking to pattern match a ClassTag on the type but I need strong type safety:
Query on a Handler, is not allowed. ask[State] must return QueryBuilder
Command and Query are the only supported types. The generic type of ask can only be a Handler or a State.
Maybe you could refactor your code to something like this?
sealed trait FooBar
sealed trait Foo extends FooBar {
def process(i: Int): Int
}
object Foo {
implicit final case object FooImpl extends Foo {
override def process(i: Int): Int = i + 1
}
}
sealed trait Bar extends FooBar {
def process(s: String): String
}
object Bar {
implicit final case object BarImpl extends Bar {
override def process(s: String): String = s.toUpperCase
}
}
object Test {
trait FooBarPartiallyApplied[FB <: FooBar] {
type Out
def out: Out
}
object FooBarPartiallyApplied {
type Aux[FB <: FooBar, _Out] = FooBarPartiallyApplied[FB] { type Out = _Out }
implicit final def FooPartiallyAppliedBuilder[F <: Foo]: Aux[F, FooPartiallyApplied[F]] =
new FooBarPartiallyApplied[F] {
override final type Out = FooPartiallyApplied[F]
override final val out: FooPartiallyApplied[F] =
new FooPartiallyApplied[F](dummy = true)
}
implicit final def BarPartiallyAppliedBuilder[B <: Bar]: Aux[B, BarPartiallyApplied[B]] =
new FooBarPartiallyApplied[B] {
override final type Out = BarPartiallyApplied[B]
override final val out: BarPartiallyApplied[B] =
new BarPartiallyApplied[B](dummy = true)
}
final class FooPartiallyApplied[F <: Foo](private val dummy: Boolean) extends AnyVal {
def toExecute(i: Int)(implicit foo: F): Int = foo.process(i)
}
final class BarPartiallyApplied[B <: Bar](private val dummy: Boolean) extends AnyVal {
def toExecute(s: String)(implicit bar: B): String = bar.process(s)
}
}
def ask[FB <: FooBar](implicit pa: FooBarPartiallyApplied[FB]): pa.Out =
pa.out
}
It works as expected:
Test.ask[Foo.FooImpl.type].toExecute(10)
// res: Int = 11
Test.ask[Foo.FooImpl.type].toExecute("blah")
// Type error.
Test.ask[Bar.BarImpl.type].toExecute(10)
// Type error.
Test.ask[Bar.BarImpl.type].toExecute("blah")
// res: String = "BLAH"

Import does not bring implicits in scope

I am facing an error about unreachable implicits in scope:
Error:(38, 68) could not find implicit value for parameter strategy: XXX.NeoStrategy[T]
(summoner: Summoner, v: String) => summoner.summonEvaluation[T](v)
I implement the answer of Tim to that question : https://stackoverflow.com/a/56668734/3896166
I tried to import the implicit object Strategies within TypeTable scope with :
import XXX.NeoStrategies._
but to no success.
The followings are each file of the base logic I want to use:
object TypeLib {
sealed trait Type_top
trait Type_A extends Type_top
trait Type_B extends Type_top
}
trait NeoStrategy[T <: Type_top] {
def evaluate(v: String, helper: Helper): Int
}
object NeoStrategies {
implicit object NeoStrategy_A extends NeoStrategy[Type_A] {
def evaluate(v: String, helper: Helper): Int = 1
}
implicit object NeoStrategy_B extends NeoStrategy[Type_B] {
def evaluate(v: String, helper: Helper): Int = 2
}
}
case class Helper(name: String) {
def summonEvaluation[T <: Type_top](v: String)(implicit strategy: NeoStrategy[T]): Int = {
strategy.evaluate(v, this)
}
}
trait TypeOMap {
protected def computeStuff[T <: Type_top]: (Helper, String) => Int
protected val computeMap: Map[String, (Helper, String) => Int]
}
import XXX.NeoStrategies._
trait TypeTable extends TypeOMap {
override protected def computeStuff[T <: Type_top]: (Helper, String) => Int = {
(helper: Helper, v: String) => helper.summonEvaluation[T](v)
}
override protected val computeMap = Map(
"a" -> computeStuff[Type_A],
"b" -> computeStuff[Type_B]
)
}
class Summoner extends TypeTable {
def callsMapAndEvaluates(typeIdentifier: String, helper: Helper, param: String): Double = {
computeMap(typeIdentifier)(helper, param)
}
}
object StackO {
def main(args: Array[String]): Unit = {
val mySummoner = new Summoner
// mySummoner allows the selecting of a given type with
// its "typeIdentifier" input in combination with the "TypeTable" it extends
val r = mySummoner.callsMapAndEvaluates("a", Helper("make it right"), "I, parameter")
}
}
This is not the first time I use implicits but not with something like the computeMap above. Still, I understand the logic of it, but fail at making it right.
How can I have summoner.summonEvaluation[T](v) find the required implicit?
Just add context bound
override protected def computeStuff[T <: Type_top : NeoStrategy] ...
It seems you want to work with singleton types. In Scala 2.12 + Shapeless
import shapeless.Witness
object TypeLib {
sealed trait Type_top
trait Type_A extends Type_top
trait Type_B extends Type_top
}
import TypeLib._
trait NeoStrategy[S <: String] {
type T <: Type_top
def evaluate(v: S, summoner: Summoner): Int
}
object NeoStrategy {
type Aux[S <: String, T0 <: Type_top] = NeoStrategy[S] { type T = T0 }
def mkStrategy[S <: String, T0 <: Type_top](f: (S, Summoner) => Int): Aux[S, T0] = new NeoStrategy[S] {
override type T = T0
override def evaluate(v: S, summoner: Summoner): Int = f(v, summoner)
}
implicit val NeoStrategy_A: NeoStrategy.Aux[Witness.`"a"`.T, Type_A] = mkStrategy((_, _) => 1)
implicit val NeoStrategy_B: NeoStrategy.Aux[Witness.`"b"`.T, Type_B] = mkStrategy((_, _) => 2)
}
case class Summoner(name: String) {
def summonEvaluation[S <: String](s: Witness.Aux[S])(implicit
strategy: NeoStrategy[S]): Int = {
strategy.evaluate(s.value, this)
}
}
def main(args: Array[String]): Unit = {
val mySummoner = Summoner("stack question")
val r = mySummoner.summonEvaluation("a")
val r1 = mySummoner.summonEvaluation("b")
println(r) // 1
println(r1) // 2
}
In Scala 2.13
object TypeLib {
sealed trait Type_top
trait Type_A extends Type_top
trait Type_B extends Type_top
}
import TypeLib._
trait NeoStrategy[S <: String with Singleton] {
type T <: Type_top
def evaluate(v: S, summoner: Summoner): Int
}
object NeoStrategy {
type Aux[S <: String with Singleton, T0 <: Type_top] = NeoStrategy[S] { type T = T0 }
def mkStrategy[S <: String with Singleton, T0 <: Type_top](f: (S, Summoner) => Int): Aux[S, T0] = new NeoStrategy[S] {
override type T = T0
override def evaluate(v: S, summoner: Summoner): Int = f(v, summoner)
}
implicit val NeoStrategy_A: NeoStrategy.Aux["a", Type_A] = mkStrategy((_, _) => 1)
implicit val NeoStrategy_B: NeoStrategy.Aux["b", Type_B] = mkStrategy((_, _) => 2)
}
case class Summoner(name: String) {
def summonEvaluation[S <: String with Singleton](s: S)(implicit
value: ValueOf[S],
strategy: NeoStrategy[S]): Int = {
strategy.evaluate(s, this)
}
}
def main(args: Array[String]): Unit = {
val mySummoner = Summoner("stack question")
val r = mySummoner.summonEvaluation("a")
val r1 = mySummoner.summonEvaluation("b")
println(r) // 1
println(r1) // 2
}
The underlying problem is this:
override protected def computeStuff[T <: Type_top]: (Helper, String) => Int = {
(helper: Helper, v: String) => helper.summonEvaluation[T](v) // implicit for NeoStrategy[T]...?
}
Since summonEvaluation[T] requires an implicit argument of type NeoStrategy[T], this means you must have one in scope for any T that's a subclass of Type_top. However, NeoStrategies only provides two instances: one for Type_A and Type_B. This is not enough for the compiler. Understandably so - for instance, you haven't provided any NeoStrategy for
Type_top itself
subclasses of Type_A and Type_B (perfectly legal to create)
There are two basic ways you can handle this:
Delaying the implicit resolution
As per the other answer, instead of trying to resolve the implicit inside computeStuff, add a context bound there too. If the point where you have to supply the implicit is only reached when you know what T is, you won't have to provide instances for any possible subtype.
Providing implicits for all possible subtypes
If absolutely you want to keep the implicit resolution inside computeStuff, you're going to have to offer a method
implicit def getNeoStrategy[T <: Type_top] : NeoStrategy[T] = ???
Unfortunately, doing this is probably going to involve a bunch of reflection and potentially runtime errors for edge cases, so I'd recommend the context bound on computeStuff.

Value * is not a member of type parameter Int

package impatient.mapsAndTups.objects
abstract class UnitConversion {
def convert[T](x: T): T
}
class Inches2Centimeters extends UnitConversion {
override def convert[Int](x: Int): Int = x * 100
}
object Conversions extends App {
val c = new Inches2Centimeters()
println(c.convert(15))
}
I'm not understanding why the preceding code is not compiling. I'm getting the error:
Error:(9, 46) value * is not a member of type parameter Int
override def convert[Int](x: Int): Int = x * 100
What can I do to fix this?
You have "shadowed" the standard type Int with your own Int within the scope of your method convert. That's because you defined convert to work with a parametric type whose name is Int and which will be defined by callers (and type inference).
One way to fix your code is the following, although I wouldn't do it this way myself.
package impatient.mapsAndTups.objects
abstract class UnitConversion {
def convert[T](x: T): T
}
class Inches2Centimeters extends UnitConversion {
def convert[T](x: T): T = x match {
case t: Int => (t * 100).asInstanceOf[T]
}
}
object Conversions extends App {
val c = new Inches2Centimeters()
println(c.convert(15))
}
Note also that you don't need to override convert in your concrete class.
Instead, I would use the "typeclass" Numeric as follows:
package impatient.mapsAndTups.objects
abstract class UnitConversion {
def convert[T: Numeric](x: T): T
}
class Inches2Centimeters extends UnitConversion {
def convert[T: Numeric](x: T): T = {
val n = implicitly[Numeric[T]]
n.times(n.fromInt(100), x)
}
}
object Conversions extends App {
val c = new Inches2Centimeters()
println(c.convert(15))
}
I think, what you want is to declare the type parameter at the class level, not function:
abstract class UnitConversion[T] {
def convert(x: T): T
}
class Inches2Centimeters extends UnitConversion[Int] {
override def convert(x: Int): Int = x * 100 // this multiplier is wrong :)
}

Scala: recursive implicit type

I have the following traits for parsing that give file positions for the beginning and end of the object:
case class FilePosn(lineNum :Int, tabs: Int, spaces: Int, fileName: String)
{/*code omitted*/}
trait PosnEnds
{
def startPosn: FilePosn
def endPosn: FilePosn
def multiLine: Boolean = startPosn.lineNum != endPosn.lineNum
def OneLine: Boolean = startPosn.lineNum == endPosn.lineNum
def indent: Int = startPosn.tabs
def startLine: Int = startPosn.lineNum
def endLine: Int = endPosn.lineNum
}
object FilePosnVoid extends FilePosn(0, 0, 0, "There is no File position")
{ override def posnString(indentSize: Int): String = "No File Posn: " }
In the companion object I create an implicit, so sequences of PosnEnds are themselves implicitly PosnEnds:
object PosnEnds
{
implicit class ImpPosnEndsSeq[A <: PosnEnds](thisSeq: Seq[A]) extends PosnEnds
{
override def startPosn: FilePosn = thisSeq.fHead(FilePosnVoid, (h, t) => h.startPosn)
override def endPosn: FilePosn = thisSeq.fLast(FilePosnVoid, _.endPosn)
}
}
Is there anyway to use implicits recursively so a Seq[Seq[A]] and a Seq[Seq[Seq[A]]] etc will be implicitly converted to a PosnEnds trait? In practice I probably won't need huge levels of depth, but it would be nice to use an elegant solution that implicitly converted Seq of arbitrary depth.
Currently for depth 2 I'm using:
implicit class ImpPosnEndsSeqSeq[A <: PosnEnds](thisSeq: Seq[Seq[A]]) extends PosnEnds
{
override def startPosn: FilePosn = thisSeq.fHead(FilePosnVoid, (h, t) => h.startPosn)
override def endPosn: FilePosn = thisSeq.fLast(FilePosnVoid, _.endPosn)
}
Yes. You could do it with typeclass mediator.
I allow myself to do some minor changes in your example to make it more reproducible. Inside object PosnEnds I have
val void = new FilePosn(0, 0, 0, "There is no File position") {
override def posnString(indentSize: Int): String = "No File Posn: "
}
def empty = new PosnEnds {
def startPosn: FilePosn = void
def endPosn: FilePosn = void
}
Thing you need first is some simple typeclass like
trait MakePosnEnds[X] extends (X => PosnEnds)
Now you can introduce canonical elements for induction:
implicit object idMakePosnEnds extends MakePosnEnds[PosnEnds] {
def apply(x: PosnEnds) = x
}
implicit def seqMakePosnEnds[X](implicit recur: MakePosnEnds[X]) = new MakePosnEnds[Seq[X]] {
def apply(x: Seq[X]): PosnEnds = new PosnEnds {
val thisSeq = x.map(recur)
override def startPosn: FilePosn = thisSeq.headOption.fold(void)(_.startPosn)
override def endPosn: FilePosn = thisSeq.lastOption.fold(void)(_.endPosn)
}
}
Finally you can define your implicit conversion
implicit def toPosnEnds[X](x: X)(implicit make: MakePosnEnds[X]): PosnEnds = make(x)
From this point
Seq(Seq(Seq(empty))).startLine
compiles and runs succesfully
Major difference with your attempt: we dont wait implicit conversion to stack. Implicit resolution can be recursive, but implicit conversion can not.
So we are using some value-less type, i.e something that could be achieved using only implicit arguments which means could be constructed by the compiler.
And only then projecting this logic to the concrete value.