Implicit parameters cannot be found when imported (from an Object) - scala

Why can not the code below find the imported implicits from MyProducers? In my understanding this should work fine because the implicits are in scope.
Error:(16, 34) could not find implicit value for evidence parameter of type MyProducers.ListProducer[Int]
val stuffInt:Int = getHead[Int]()
Error:(16, 34) not enough arguments for method getHead: (implicit evidence$2: MyProducers.ListProducer[Int])Int.
Unspecified value parameter evidence$2.
val stuffInt:Int = getHead[Int]()
Error:(18, 43) could not find implicit value for evidence parameter of type MyProducers.ListProducer[String]
val stuffString:String = getHead[String]()
Error:(18, 43) not enough arguments for method getHead: (implicit evidence$2: MyProducers.ListProducer[String])String.
Unspecified value parameter evidence$2.
val stuffString:String = getHead[String]()
Code:
object Resolver {
import MyProducers._
import MyProducers._
def getList[T:ListProducer]():List[T]= implicitly[ListProducer[T]].produceList
def getHead[T:ListProducer]():T= getList[T]().head
val stuffInt:Int = getHead[Int]()
val stuffString:String = getHead[String]()
val im=ip // this compiles fine, so implicits are in scope
val sm=sp
}
object MyProducers{
trait ListProducer[T]{
def produceList:List[T]
}
object IntProducer extends ListProducer[Int]{
override def produceList = List(22, 42)
}
implicit val ip=IntProducer
object StringProducer extends ListProducer[String]{
override def produceList = List("stuff", "Shiraly")
}
implicit val sp=StringProducer
}
What is strange, that this code compiles fine:
object Resolver {
import MyProducers._
import MyProducers._
trait ListProducer[T]{
def produceList:List[T]
}
object IntProducer extends ListProducer[Int]{
override def produceList = List(22, 42)
}
implicit val ip=IntProducer
object StringProducer extends ListProducer[String]{
override def produceList = List("stuff", "Shiraly")
}
implicit val sp=StringProducer
def getList[T:ListProducer]():List[T]= implicitly[ListProducer[T]].produceList
def getHead[T:ListProducer]():T= getList[T]().head
val stuffInt:Int = getHead[Int]()
val stuffString:String = getHead[String]()
val im=ip
val sm=sp
}
Any idea why the first code does not compile while the second does ?

Implicit vals and defs need to have type annotations on them. Add those, and the implicits will be found.

Related

Kafka Streams: SessionWindowedSerde Vs TimeWindowedSerde. Ambiguous implicit values

I keep getting 'ambiguous implicit values' message in the following code. I tried several things (as can be seen from a couple of lines I've commented out). Any ideas on how to fix this? This is in Scala.
def createTopology(conf: Config, properties: Properties): Topology = {
// implicit val sessionSerde = Serde[WindowedSerdes.SessionWindowedSerde[String]]
// implicit val produced: Produced[Windowed[String], Long] = Produced.`with`[WindowedSerdes.SessionWindowedSerde[String], Long]
implicit val produced: Produced[Windowed[String], Long] = Produced.`with`[Windowed[String], Long]
implicit val consumed: Consumed[String, String] = Consumed.`with`[String, String]
val builder: StreamsBuilder = new StreamsBuilder()
builder.stream("streams-plaintext-input")
.groupBy((_, word) => word)
.windowedBy(SessionWindows.`with`(Duration.ofMillis(60 * 1000)))
.count()
.toStream.to("streams-pipe-output")
builder.build()
}
Compiler Errors:
Error:(52, 78) ambiguous implicit values:
both method timeWindowedSerde in object Serdes of type [T](implicit tSerde: org.apache.kafka.common.serialization.Serde[T])org.apache.kafka.streams.kstream.WindowedSerdes.TimeWindowedSerde[T]
and method sessionWindowedSerde in object Serdes of type [T](implicit tSerde: org.apache.kafka.common.serialization.Serde[T])org.apache.kafka.streams.kstream.WindowedSerdes.SessionWindowedSerde[T]
match expected type org.apache.kafka.common.serialization.Serde[org.apache.kafka.streams.kstream.Windowed[String]]
implicit val produced: Produced[Windowed[String], Long] = Produced.`with`[Windowed[String], Long]
Error:(52, 78) could not find implicit value for parameter keySerde: org.apache.kafka.common.serialization.Serde[org.apache.kafka.streams.kstream.Windowed[String]]
implicit val produced: Produced[Windowed[String], Long] = Produced.`with`[Windowed[String], Long]
Error:(52, 78) not enough arguments for method with: (implicit keySerde: org.apache.kafka.common.serialization.Serde[org.apache.kafka.streams.kstream.Windowed[String]], implicit valueSerde: org.apache.kafka.common.serialization.Serde[Long])org.apache.kafka.streams.kstream.Produced[org.apache.kafka.streams.kstream.Windowed[String],Long].
Unspecified value parameters keySerde, valueSerde.
implicit val produced: Produced[Windowed[String], Long] = Produced.`with`[Windowed[String], Long]
I just add some implicits by adding imports and it compiles:
import org.apache.kafka.common.serialization.Serde
import org.apache.kafka.streams.Topology
import org.apache.kafka.streams.kstream.{SessionWindows, Windowed}
import org.apache.kafka.streams.scala.StreamsBuilder
import org.apache.kafka.streams.scala.kstream.{Consumed, Produced}
import java.time.Duration
import java.util.Properties
import org.apache.kafka.streams.scala.ImplicitConversions._
import org.apache.kafka.streams.scala.Serdes
import org.apache.kafka.streams.scala.Serdes.{Long, String}
def createTopology(conf: Config, properties: Properties): Topology = {
// here we have two implicits to choose, I pick the sessionWindowedSerde because it was in your code
// implicit val timeWindowedSerde: Serde[Windowed[String]] = Serdes.timeWindowedSerde[String]
implicit val sessionSerde: Serde[Windowed[String]] = Serdes.sessionWindowedSerde[String]
implicit val produced: Produced[Windowed[String], Long] = Produced.`with`[Windowed[String], Long]
implicit val consumed: Consumed[String, String] = Consumed.`with`[String, String]
val builder: StreamsBuilder = new StreamsBuilder()
builder.stream("streams-plaintext-input")
.groupBy((_, word) => word)
.windowedBy(SessionWindows.`with`(Duration.ofMillis(60 * 1000)))
.count()
.toStream.to("streams-pipe-output")
builder.build()
}
If you see an error:
ambiguous implicit values
it means in your scope defined more than one implicits which satisfying the needed types. For example object org.apache.kafka.streams.scala.Serdes has a two implicits:
implicit def timeWindowedSerde[T](implicit tSerde: Serde[T]): WindowedSerdes.TimeWindowedSerde[T] =
new WindowedSerdes.TimeWindowedSerde[T](tSerde)
implicit def sessionWindowedSerde[T](implicit tSerde: Serde[T]): WindowedSerdes.SessionWindowedSerde[T] =
new WindowedSerdes.SessionWindowedSerde[T](tSerde)
where TimeWindowedSerde extends Serdes.WrapperSerde<Windowed<T>>:
static public class TimeWindowedSerde<T> extends Serdes.WrapperSerde<Windowed<T>>
and SessionWindowedSerde extends Serdes.WrapperSerde<Windowed<T>>:
static public class SessionWindowedSerde<T> extends Serdes.WrapperSerde<Windowed<T>>
both of them extends the same type Serdes.WrapperSerde<Windowed<T>>,
and in the line:
implicit val produced: Produced[Windowed[String], Long] = Produced.`with`[Windowed[String], Long]
according to with function signature:
def `with`[K, V](implicit keySerde: Serde[K], valueSerde: Serde[V]): ProducedJ[K, V] =
ProducedJ.`with`(keySerde, valueSerde)
we expect some implicit value for Serde[Windowed[String]] and compiler can't pick one because both of them are Serde[Windowed[String]].
So if you just try to add both of them to the same scope:
implicit val timeWindowedSerde: Serde[Windowed[String]] = Serdes.timeWindowedSerde[String]
implicit val sessionSerde: Serde[Windowed[String]] = Serdes.sessionWindowedSerde[String]
you will see
ambiguous implicit values
again.
Conclusion: be careful while importing large bunches of implicits and the best practice is to import only implicits that you needed.

scala circe encoders/decoders for an abstract class with case classes

I want to save a collection of FieldMapping classes as a json string -
abstract class Field {
def clazz: Class[_]
def name: String
}
case class StringField(name: String) extends Field {
override def clazz: Class[_] = classOf[String]
}
case class DateField(name: String) extends Field {
override def clazz: Class[_] = classOf[Date]
}
... etc - full code here:
https://github.com/alexeyOnGitHub/scala-typesafe/blob/master/src/main/scala/com/example/model/Field.scala
Circe code:
import com.example.model.{DateField, Field, FieldMapping, StringField}
import io.circe.generic.semiauto.{deriveDecoder, deriveEncoder}
import io.circe.{Decoder, Encoder}
object CirceBoilerplateForConfigs {
implicit val fieldDecoder: Decoder[StringField] = deriveDecoder[StringField]
implicit val fieldEncoder: Encoder[StringField] = deriveEncoder[StringField]
implicit val dateDecoder: Decoder[DateField] = deriveDecoder[DateField]
implicit val dateEncoder: Encoder[DateField] = deriveEncoder[DateField]
implicit val fooDecoder: Decoder[FieldMapping] = deriveDecoder[FieldMapping]
implicit val fooEncoder: Encoder[FieldMapping] = deriveEncoder[FieldMapping]
}
Error:(14, 65) could not find Lazy implicit value of type
io.circe.generic.decoding.DerivedDecoder[com.example.model.FieldMapping]
implicit val fooDecoder: Decoder[FieldMapping] =
deriveDecoder[FieldMapping] Error:(14, 65)
not enough arguments for method deriveDecoder: (implicit decode:
shapeless.Lazy[io.circe.generic.decoding.DerivedDecoder[com.example.model.FieldMapping]])io.circe.Decoder[com.example.model.FieldMapping].
Unspecified value parameter decode. implicit val fooDecoder:
Decoder[FieldMapping] = deriveDecoder[FieldMapping] Error:(15, 65)
could not find Lazy implicit value of type
io.circe.generic.encoding.DerivedObjectEncoder[com.example.model.FieldMapping]
implicit val fooEncoder: Encoder[FieldMapping] =
deriveEncoder[FieldMapping] Error:(15, 65)
not enough arguments for
method deriveEncoder: (implicit encode:
shapeless.Lazy[io.circe.generic.encoding.DerivedObjectEncoder[com.example.model.FieldMapping]])io.circe.ObjectEncoder[com.example.model.FieldMapping].
Unspecified value parameter encode. implicit val fooEncoder:
Encoder[FieldMapping] = deriveEncoder[FieldMapping]
Field should be a sealed trait (with abstract class or not sealed trait this won't work).
The following code compiles:
import java.util.Date
sealed trait Field {
def clazz: Class[_]
def name: String
}
case class StringField(name: String) extends Field {
override def clazz: Class[_] = classOf[String]
}
case class DateField(name: String) extends Field {
override def clazz: Class[_] = classOf[Date]
}
case class FieldMapping(fieldInConnector1: Option[Field],
fieldInConnector2: Option[Field],
selected: Boolean,
defaultValue: String)
import io.circe.generic.semiauto.{deriveDecoder, deriveEncoder}
import io.circe.{Decoder, Encoder}
object CirceBoilerplateForConfigs {
implicit val stringDecoder: Decoder[StringField] = deriveDecoder[StringField]
implicit val stringEncoder: Encoder[StringField] = deriveEncoder[StringField]
implicit val dateDecoder: Decoder[DateField] = deriveDecoder[DateField]
implicit val dateEncoder: Encoder[DateField] = deriveEncoder[DateField]
implicit val fieldDecoder: Decoder[Field] = deriveDecoder[Field]
implicit val fieldEncoder: Encoder[Field] = deriveEncoder[Field]
implicit val fooDecoder: Decoder[FieldMapping] = deriveDecoder[FieldMapping]
implicit val fooEncoder: Encoder[FieldMapping] = deriveEncoder[FieldMapping]
}

Scala - implicit macros & materialisation

The use cases for implicit macros is supposed to be the so-called "materialisation" of type class instances.
Unfortunately, the example in the documentation is a bit vague on how that is achieved.
Upon being invoked, the materializer can acquire a representation of T and generate the appropriate instance of the Showable type class.
Let's say I have the following trait ...
trait PrettyPrinter[T]{
def printed(x:T) : String
}
object PrettyPrinter{
def pretty[T](x:T)(implicit pretty:PrettyPrinter[T]) = pretty printed x
implicit def prettyList[T](implicit pretty :PrettyPrinter[T]) = new PrettyPrinter[List[T]] {
def printed(x:List[T]) = x.map(pretty.printed).mkString("List(",", ",")")
}
}
and three test classes
class A(val x:Int)
class B(val x:Int)
class C(val x:Int)
Now I understand that instead of writing the following boilerplate
implicit def aPrinter = new PrettyPrinter[A] {def printed(a:A) = s"A(${a.x})"}
implicit def bPrinter = new PrettyPrinter[B] {def printed(b:B) = s"B(${b.x})"}
implicit def cPrinter = new PrettyPrinter[C] {def printed(c:C) = s"C(${c.x})"}
we should be able to add
implicit def materialise[T] : PrettyPrinter[T] = macro implMaterialise[T]
def implMaterialise[T](c:blackbox.Context):c.Expr[PrettyPrinter[T]] = {
import c.universe._
???
}
to the object PrettyPrinter{...} which then generates the corresponding PrettyPrinters on demand ... how? How do I actually get that "representation of T"?
If I try c.typeOf[T], for example, "No TypeTag available for T".
UPDATE
Trying to use class tags doesn't seem to work either.
implicit def materialise[T:ClassTag] : PrettyPrinter[T] = macro implMaterialise[T]
def implMaterialise[T:ClassTag](c:blackbox.Context):c.Expr[PrettyPrinter[T]] = {
import c.universe._
???
}
results in
Error:(17, 69) macro implementations cannot have implicit parameters other than WeakTypeTag evidences
implicit def materialise[T:ClassTag] : PrettyPrinter[T] = macro implMaterialise[T]
^
update2
Interestingly, using WeakTypeTags doesn't really change anything as
implicit def materialise[T:WeakTypeTag]: PrettyPrinter[T] = macro implMaterialise[T]
def implMaterialise[T](c:blackbox.Context)(implicit evidence : WeakTypeTag[T]):c.Expr[PrettyPrinter[T]]
= {
import c.universe._
???
}
will result in
Error:(18, 71) macro implementations cannot have implicit parameters other than WeakTypeTag evidences
implicit def materialise[T:WeakTypeTag]: PrettyPrinter[T] = macro implMaterialise[T]
^
How do I actually get that "representation of T"?
You need to use c.WeakTypeTag, as hinted at by the compiler message you found in your "UPDATE" section.
This project has a working example that you can adapt: https://github.com/underscoreio/essential-macros/blob/master/printtype/lib/src/main/scala/PrintType.scala
object PrintTypeApp extends App {
import PrintType._
printSymbol[List[Int]]
}
import scala.language.experimental.macros
import scala.reflect.macros.blackbox.Context
import scala.util.{ Try => ScalaTry }
object PrintType {
// Macro that generates a `println` statement to print
// declaration information of type `A`.
//
// This only prints meaningful output if we can inspect
// `A` to get at its definition:
def printSymbol[A]: Unit =
macro PrintTypeMacros.printTypeSymbolMacro[A]
}
class PrintTypeMacros(val c: Context) {
import c.universe._
def printTypeSymbolMacro[A: c.WeakTypeTag]: c.Tree =
printSymbol(weakTypeOf[A].typeSymbol, "")
}

How to fix this typeclass example?

This is a follow-up to my previous question:
Suppose I create the following test converter.scala:
trait ConverterTo[T] {
def convert(s: String): Option[T]
}
object Converters {
implicit val toInt: ConverterTo[Int] =
new ConverterTo[Int] {
def convert(s: String) = scala.util.Try(s.toInt).toOption
}
}
class A {
import Converters._
def foo[T](s: String)(implicit ct: ConverterTo[T]) = ct.convert(s)
}
Now when I tried to call foo in REPL it fails to compile:
scala> :load converter.scala
Loading converter.scala...
defined trait ConverterTo
defined module Converters
defined class A
scala> val a = new A()
scala> a.foo[Int]("0")
<console>:12: error: could not find implicit value for parameter ct: ConverterTo[Int]
a.foo[Int]("0")
^
import Converters._ in class A does not cut it. You can remove it and the code will still compile. The moment the compiler needs to find in actual implicit is not in class A, where foo is just declared.
The compiler needs to find a ConverterTo[Int] in implicit scope at the moment you call a.foo[Int](..) that is in the REPL. So this is where the import needs to be.
Had object Converters and trait ConverterTo been named the same (so there would be a companion object) the import would not be needed.

No ClassTag available compilation error

The compiler keeps producing the following errors:
No ClassTag available for a
val keys = Array.fill(maxSize+1){ default[a] }
^
not enough arguments for method fill: (implicit evidence$9: scala.reflect.ClassTag[a])Array[a].
Unspecified value parameter evidence$9.
val keys = Array.fill(maxSize+1){ default[a] }
^
for this piece of code
object Utils {
def default[a] = {
class DefaultVal {
var x: a = _
}
(new DefaultVal).x
}
}
class IndexedHeap[a](maxSize: Int)(implicit ev: Ordering[a]) {
import ev._
import Utils._
val keys = Array.fill(maxSize+1){ default[a] }
}
Any ideas on how to fix this?
I think adding ClassTag would fix it, like this:
[a:ClassTag]
edit based on your comment on the conflict with implicit params and context bounds:
Change the implicit parameters to include the ClassTag too
implicit ev: Ordering[a], ct: ClassTag[a]