0

I am reading Hands-on Scala Programming and I am stuck on recursive typeclass inference.

The section explains how to write a parser from multiple data types. It gives the example below

trait StrParser[T]{ def parse(s: String): T }
object StrParser{
  implicit object ParseInt extends StrParser[Int]{
    def parse(s: String) = s.toInt
  }
  implicit object ParseBoolean extends StrParser[Boolean]{
    def parse(s: String) = s.toBoolean
  }
  implicit object ParseDouble extends StrParser[Double]{
    def parse(s: String) = s.toDouble
  }
}

The above code works well. After that, it moves on to recursive typeclass inference. It shows an implication function below.

implicit def ParseSeq[Int](implicit p: StrParser[Int]) = new StrParser[Seq[Int]]{
  def parse(s: String) = s.split(',').toSeq.map(p.parse)
}

However, I face an error after I ran this code. I tried it on Ammonite, Scala, and compile it but everything does not work.

result type of implicit definition needs to be given explicit

I look up the error on google and only found two non-related results. How can I fix this issue? What am I missing?

6
  • 2
    First, you don't want to name your generic Int, that would be confusing, use a single letter like A or T - Second, the error is pretty clear, you have to be explicit with the return type of your implicit def try: implicit def ParseSeq[T](implicit ev: StrParser[T]): StrParser[Seq[T]] = Commented Aug 18, 2021 at 14:52
  • @LuisMiguelMejíaSuárez where can I read more about explicit return type? I am new to Scala Commented Aug 18, 2021 at 15:31
  • Sorry, not sure what you mean? BTW, if you are new to the language maybe you would want to join the Discord server which would be better for this kind of questions. Commented Aug 18, 2021 at 15:37
  • Thank you for the link. I will join it. For my question, I want to understand why I need to explicitly specify the result type in Scala 3. It seems like a breaking change and I want to know the reason behind it. Commented Aug 18, 2021 at 15:58
  • 2
    To be honest no idea, the technically correct answer is because the compiler says so, period. Anyways, you always want to be explicit with return types, which helps with documentation and catching bugs. Commented Aug 18, 2021 at 16:01

1 Answer 1

3

The book is written for Scala 2, which handles this code without error:

trait StrParser[T]{ def parse(s: String): T }
object StrParser{
  implicit object ParseInt extends StrParser[Int]{
    def parse(s: String) = s.toInt
  }
  implicit object ParseBoolean extends StrParser[Boolean]{
    def parse(s: String) = s.toBoolean
  }
  implicit object ParseDouble extends StrParser[Double]{
    def parse(s: String) = s.toDouble
  }
}

implicit def ParseSeq[T](implicit p: StrParser[T]) = new StrParser[Seq[T]]{
  def parse(s: String) = s.split(',').toSeq.map(p.parse)
}

def parseFromString[T](s: String)(implicit parser: StrParser[T]) = {
  parser.parse(s)
}

parseFromString[Seq[Int]]("1,1")

It seems that you are using Scala 3, for it you will need to change your ParseSeq definition to:

implicit def ParseSeq[T](implicit p: StrParser[T]): StrParser[Seq[T]] = new StrParser[Seq[T]]{
  def parse(s: String) = s.split(',').toSeq.map(p.parse)
}

Also note that the book defines ParseSeq as a generic method with parameter name T, which is better generic parameter name than one mathcing existing type (i.e. Int):

implicit def ParseSeq[T](implicit p: StrParser[T]) = new StrParser[Seq[T]]{
  def parse(s: String) = s.split(',').toSeq.map(p.parse)
}
Sign up to request clarification or add additional context in comments.

3 Comments

If the error only happens on Scala 3 wouldn't it better to use given / using?
What is this called in Scala 3? Where can I read more about this?
@CodeProject it is a new version of language.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.