Simple Type Inference in Method Arguments

62 views
Skip to first unread message

Volkan Yazıcı

unread,
May 13, 2015, 8:18:15 AM5/13/15
to scala...@googlegroups.com
Hello,

Why Scala cannot infer the type of a parameter passed via a named argument. That is, in the following snippet

trait StringReader[T] {

  def fromString(input: String): T

}

object StringReader {

  def fromString[T: StringReader](input: String)(implicit reader: StringReader[T]): T =
    reader.fromString(input)

  implicit object IntStringReader extends StringReader[Int] {

    def fromString(input: String): Int = input.toInt

  }

  implicit object DoubleStringReader extends StringReader[Double] {

    def fromString(input: String): Double = input.toDouble

  }

}

import StringReader.fromString

case class Token(intField: Int, doubleField: Double)

val token = Token(intField = fromString("1"), doubleField = fromString("1.0"))

//Error:(30, 46) ambiguous implicit values:
//  both object IntStringReader in object StringReader of type A$A42.this.StringReader.IntStringReader.type
//and object DoubleStringReader in object StringReader of type A$A42.this.StringReader.DoubleStringReader.type
//match expected type A$A42.this.StringReader[T]
//lazy val token = Token(intField = fromString("1"), doubleField = fromString("1.0"))
//^

can't I avoid providing explicit type parameters to fromString calls? I mean, is there a way to make this work without using fromString[Int]("1")?

Best.

Oliver Ruebenacker

unread,
May 13, 2015, 8:56:24 AM5/13/15
to Volkan Yazıcı, scala-user

     Hello,

  Wouldn't plain vanilla implicit conversions work for you, or what are you trying to achieve?

  import scala.language.implicitConversions

  implicit def string2Int(s: String): Int = augmentString(s).toInt
  implicit def string2Double(s: String): Double = augmentString(s).toDouble

  case class Token(intField: Int, doubleField: Double)

  val token = Token(intField = "1", doubleField = "1.0")

     Best, Oliver


--
You received this message because you are subscribed to the Google Groups "scala-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-user+...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.



--
Oliver Ruebenacker
Solutions Architect at Altisource Labs
Be always grateful, but never satisfied.

Volkan Yazıcı

unread,
May 13, 2015, 9:10:46 AM5/13/15
to scala...@googlegroups.com, volkan...@gmail.com
Internally, I have a set of StringReader[T] objects for various Ts already in place and I want to employ them in a couple of places, where StringReader.fromString was one such example. Nevertheless, I would expect Scala to infer the relevant type, hence, I also wondered why my example did not work and requires explicit typing. 

Volkan Yazıcı

unread,
May 13, 2015, 9:30:42 AM5/13/15
to scala...@googlegroups.com
Additionally, a similar approach is also used in ScalikeJDBC. That is,

object MappingRecord extends SfmRichSQLSyntaxSupport[MappingRecord] {

  override val tableName = "MAPPINGS"

  def apply(rn: ResultName[MappingRecord])(rs: WrappedResultSet): MappingRecord = {
    import TypeBinders._
    new MappingRecord(
      id = rs.int(rn.id),
      reference_id = rs.int(rn.reference_id),
      reference_type = rs.get(rn.reference_type),
      property_name = rs.string(rn.property_name))
  }

}

and WrappedResultSet#get(String) is defined as follows:

def get[A: TypeBinder](columnLabel: String): A = {
  ensureCursor()
  wrapIfError(implicitly[TypeBinder[A]].apply(underlying, columnLabel))
}

and it perfectly manages to infer relevant type A: TypeBinder as expected. Hence, I believe I am missing something but I could not figure out what.

Nils Kilden-Pedersen

unread,
May 13, 2015, 12:58:38 PM5/13/15
to Volkan Yazıcı, scala-user

On Wed, May 13, 2015 at 7:18 AM, Volkan Yazıcı <volkan...@gmail.com> wrote:

Hello,

Why Scala cannot infer the type of a parameter passed via a named argument. That is, in the following snippet

trait StringReader[T] {

  def fromString(input: String): T

}

object StringReader {

  def fromString[T: StringReader](input: String)(implicit reader: StringReader[T]): T =

Here you are actually passing two implicit StringReaders. Either have an explicit (!) implicit, or use the [T: StringReader] syntax and access it via implicitly[StringReader[T]].

    reader.fromString(input)

  implicit object IntStringReader extends StringReader[Int] {

    def fromString(input: String): Int = input.toInt

  }

  implicit object DoubleStringReader extends StringReader[Double] {

    def fromString(input: String): Double = input.toDouble

  }

}

import StringReader.fromString

case class Token(intField: Int, doubleField: Double)

val token = Token(intField = fromString("1"), doubleField = fromString("1.0"))

//Error:(30, 46) ambiguous implicit values:
//  both object IntStringReader in object StringReader of type A$A42.this.StringReader.IntStringReader.type
//and object DoubleStringReader in object StringReader of type A$A42.this.StringReader.DoubleStringReader.type
//match expected type A$A42.this.StringReader[T]
//lazy val token = Token(intField = fromString("1"), doubleField = fromString("1.0"))
//^

can't I avoid providing explicit type parameters to fromString calls? I mean, is there a way to make this work without using fromString[Int]("1")?

Best.

--

Volkan Yazıcı

unread,
May 15, 2015, 2:46:19 AM5/15/15
to Nils Kilden-Pedersen, scala-user
Admitting the fact that it has nothing to do with question, thanks for the tip Nils. I used both the context bound and the implicit parameter intentionally. That is, if I am not mistaken, context bound provides a stronger hint for the IDE to figure out compile-time problems on-the-fly while typing in the editor. That being said, you have a point. Having both of them is sort of redundant. Does it have any performance impact at all? 
Reply all
Reply to author
Forward
0 new messages