configs
configs copied to clipboard
Problem reading lists of non-trivial types
Hi
I have come across an interesting problem when using configs version 0.4.4 and 0.5.0-SNAPSHOT (22ad412d17c104930d63be05bd67474b55745434) with scala 2.11.
Example:
object MyEnum extends Enumeration {
type MyEnum = Value
val Foo = Value("foo")
val Bar = Value("bar")
}
case class Foo2(enum: Option[MyEnum])
Reading this class from a config works:
val config2_0 = ConfigFactory.parseString("foo = {enum = foo}")
val result2_0 = ConfigReader[Foo2].read(config2_0, "foo")
println(result2_0)
However, reading a List (or Seq) of this class does not compile!
val config2_1 = ConfigFactory.parseString("foo = [{enum = foo}, {enum = bar}]")
val result2_1 = ConfigReader[List[Foo2]].read(config2_1, "foo")
println(result2_1)
Error:(36, 33) diverging implicit expansion for type configs.ConfigReader[java.util.List[Foo2]]
starting with method fromStringConfigReader in class ConfigReaderInstances
val result2_1 = ConfigReader[List[Foo2]].read(config2_1, "foo")
Error:(36, 33) diverging implicit expansion for type configs.ConfigReader[Option[MyEnum.MyEnum]]
starting with macro method autoDeriveConfigReader in class ConfigReaderInstances3
val result2_1 = ConfigReader[List[Foo2]].read(config2_1, "foo")
Error:(36, 33) not enough arguments for method apply: (implicit A: configs.ConfigReader[List[Foo2]])configs.ConfigReader[List[Foo2]] in object ConfigReader.
Unspecified value parameter A.
val result2_1 = ConfigReader[List[Foo2]].read(config2_1, "foo")
The same problem appears in other similar cases. For example:
case class EitherExample(num: Either[Int, String])
with the following reader:
implicit def eitherReader[A, B](implicit aReader: ConfigReader[A], bReader: ConfigReader[B]): ConfigReader[Either[A, B]] = {
ConfigReader.fromTry { (c, p) =>
aReader.read(c, p).map(Left(_)).orElse(bReader.read(c, p).map(Right(_))).valueOrThrow(_.configException)
}
}
Reading this class from a config works:
val config3_0 = ConfigFactory.parseString("{num = two}")
val result3_0 = ConfigReader[EitherExample].extract(config3_0)
println(result3_0)
However, reading a List (or Seq) of this class does not compile!
val config3_1 = ConfigFactory.parseString("foo = [{num = 2}, {num = two}]")
val result3_1 = ConfigReader[List[EitherExample]].read(config3_1, "foo")
print(result3_1)
Error:(44, 33) diverging implicit expansion for type configs.ConfigReader[Either[Int,String]]
starting with method eitherReader in object Bug
val result3_1 = ConfigReader[List[EitherExample]].read(config3_1, "foo")
Error:(44, 33) diverging implicit expansion for type configs.ConfigReader[java.util.List[EitherExample]]
starting with method fromStringConfigReader in class ConfigReaderInstances
val result3_1 = ConfigReader[List[EitherExample]].read(config3_1, "foo")
Error:(44, 33) diverging implicit expansion for type configs.ConfigReader[Either[Int,String]]
starting with macro method autoDeriveConfigReader in class ConfigReaderInstances3
val result3_1 = ConfigReader[List[EitherExample]].read(config3_1, "foo")
Error:(44, 33) not enough arguments for method apply: (implicit A: configs.ConfigReader[List[EitherExample]])configs.ConfigReader[List[EitherExample]] in object ConfigReader.
Unspecified value parameter A.
val result3_1 = ConfigReader[List[EitherExample]].read(config3_1, "foo")
Note: All examples compile and run with Scala 2.13. However, I do not have the option to upgrade beyond 2.11 in the project I am working on.
Any clues as to what is happening and whether it can be fixed or avoided?
Thank you!
We found a workaround (hopefully) which may help to shed some light on what is happening.
The examples above work, when the "pimp my library" decorator for the typesafe Config is used instead of ConfigReader[A].
These work:
import configs.syntax._
val result2_1 = config2_1.get[List[Foo2]]("foo")
val result3_1 = config3_1.get[List[EitherExample]]("foo")