shapeless: Generic programming for Scala | This room deprecated in favour of #shapeless on the Typelevel Discord: https://discord.gg/bSQBZA3Ced
joroKr21 on main
Update sbt-scalajs, scalajs-com… (compare)
joroKr21 on main
Update scala-parser-combinators… (compare)
joroKr21 on main
Update junit-plugin, junit-runt… (compare)
joroKr21 on main
Update sbt to 1.8.2 (#1296) (compare)
joroKr21 on main
Fixed typo (#1295) (compare)
joroKr21 on main
Update slf4j-nop to 2.0.6 (#129… (compare)
Hi all, is there machinery in shapeless (or elsewhere) allowing you to prove that a particular implicit instance is NOT in scope? I.e.
trait Foo
implicit val foo = new Foo {}
implicitly[Not[Foo]] // Err: "Implicit instance for Foo in scope."
I have something that works but I'm wondering if someone thought about this in more depth before.
Generic[MyData]
leads to a stack overflow. Is there any good way around this?
LabelledGeneric
, but I can move forward without those for now
hi guys, I have encountered a very interesting issue which I can't really explain but maybe somebody here faced something similar. We use Scanamo in our web application for DynamoDB access. Scanamo uses shapeless internally for conversion between case classes and dynamodb data model. Basically, for this to work there should be implicit formatter in scope for the case class, these formatters are automatically derived via shapeless. I once added a new field to my case class and noticed that tests started blocking infinitely. After hours spent debugging I found out that the place that actually hangs forever is the call to LabelledGeneric.from
during the derivation phase but when I tried to evaluate this expression in Intellij debugger it showed me that there is an exception
java.lang.NoSuchMethodError: somepackage.MyCaseClass.<init>(Lscala/Option;Lscala/Option;Ljava/lang/Double;)V
what is interesting here is that this list of parameters doesn't include my new field even though its in code. What is even more interesting is that when I tried to summon the implicit for the formatter on the very high level in my application code like implicitly[DynamoFormat[MyCaseClass]]
all code started working again without any blockage and even after I removed this line. When I added new fields again in future I had no problems with it but my colleagues had the same issue. To me it looks like shapeless somehow loads the old (cached somewhere?) version of case class in the situation where code blocks but why then the exception is not thrown? Has anybody seen something similar? Thanks in advance.
Map[String, Any]
Could Shapeless help to eliminate the following boiler plate?
Please consider a trait called Navigable. Any class that extends this trait must implement a method that takes a path as a parameter and returns the value at the end of the path. The path encodes steps through the object graph reachable from this object. For example, the path: "foo/8/colors/red" might correspond to this.foo(8).colors.get("red"); that is, a dot access, an array access, then a map retrieval.
We can assume constraints on Navigable objects: 1. They always consist of directed acyclic object graphs. 2. They only reference primitives, maps, arrays, and other Navigable objects.
Can shapeless eliminate the need to write path comprehension code for every single Navigable type?
@SystemFw Thanks for the suggestion. I have looked into lenses and the Monocle library. If you write code to declare how they compose with each other, Lenses simulate object mutations by simplifying the process of creating copies of all of the nodes in an object graph.
How does that relate to parsing a path of the form: "foo/8/colors/red" into a series of field, array, and map accesses?
@DmytroMitin So I'm trying
implicit def hconsFromMap0list[K <: Symbol, V, R <: HList, T <: HList](implicit
witness: Witness.Aux[K],
gen: LabelledGeneric.Aux[V, R],
fromMapH: FromMap[R],
fromMapT: FromMap[T]
): FromMap[FieldType[K, List[V]] :: T] =
new FromMap[FieldType[K, List[V]] :: T] {
def apply(m: Map[String, Any]): Option[FieldType[K, List[V]] :: T] = (for {
v <- m.get(witness.value.name)
r <- Typeable[Map[String, Any]].cast(v)
h <- fromMapH(r)
t <- fromMapT(m)
} yield field[K](List(gen.from(h))) :: t).orElse(for {
v <- m.get(witness.value.name)
r1 <- Typeable[List[Map[String, Any]]].cast(v)
opt = for {
r <- r1
h <- fromMapH(r)
} yield gen.from(h)
t <- fromMapT(m)
} yield field[K](opt) :: t)
}
But the following test fails with NSEE None.get
case class NestedFoo(foos: Option[List[Foo]])
case class Foo(foo: String)
"NestedFoo" in {
val map = Map[String, Any]("foos" -> Some(List(Map("foo" -> "value"), Map("foo" -> "value2"))))
CaseClassFromMap[NestedFoo](map) must_=== NestedFoo(foos = Some(List(
Foo(
foo = "value"
),
Foo(
foo = "value2"
)
)))
}
case class NestedFoo(foos: List[Foo])
CaseClassFromMap[NestedFoo](Map("foos" -> List(Map("foo" -> "value"), Map("foo" -> "value2")))) \\ NestedFoo(List(Foo(value), Foo(value2)))
CaseClassFromMap[NestedFoo](Map("foos" -> Map("foo" -> "value"))) \\ NestedFoo(List(Foo(value)))
@DmytroMitin I guess what I'm hoping for is some magic since there are infinite number of combinations of List[List
or List[Option[Option
or List[List[Option
etc. If there was a way to combine the type-class for List
automagically with Option
for any combination of nestings that would be cool.
But in case that request is impossible, it would be nice if you could help me figure out how to just get one level of nesting working. I'm a bit stuck on Option[List[
. This is what I have got so far
implicit def hconsFromMap0optList[K <: Symbol, V, R <: HList, T <: HList](implicit
witness: Witness.Aux[K],
gen: LabelledGeneric.Aux[V, R],
fromMapH: FromMap[R],
fromMapT: FromMap[T]
): FromMap[FieldType[K, Option[List[V]]] :: T] =
new FromMap[FieldType[K, Option[List[V]]] :: T] {
def apply(m: Map[String, Any]): Option[FieldType[K, Option[List[V]]] :: T] = (for {
v <- m.get(witness.value.name)
r <- Typeable[Map[String, Any]].cast(v)
h <- fromMapH(r)
t <- fromMapT(m)
} yield field[K](Some(List(gen.from(h)))) :: t).orElse(for {
v <- m.get(witness.value.name)
r1 <- Typeable[Option[List[Map[String, Any]]]].cast(v)
opt = for {
r <- r1
h <- fromMapH(r)
list = for {
r2 <- r
h2 <- fromMapH(r2)
} yield gen.from(h2)
} yield ???
t <- fromMapT(m)
} yield field[K](opt) :: t)
}
As you can see I'm a bit confused on how to get the for-comprehensions to work with this extra level of nesting.
Again appreciate the help! I'm very new to Shapeless.
m.instances
I'm assuming? Can you point me somewhere where I can learn more? Is there documentation that would help? Googling shapless LiftAll didn't get me much. All I've ever done with shapeless is basic HList stuff.