magnolia icon indicating copy to clipboard operation
magnolia copied to clipboard

Given a sealed trait, expose all of its case class subtypes's names in ctx in dispatch function

Open gaoxinyang opened this issue 5 years ago • 6 comments

We have a simple use case which is similar to the decode.scala example, https://github.com/propensive/magnolia/blob/master/examples/shared/src/main/scala/decode.scala#L49

We want to decode sth into an instance of a Scala case class, given the type of the root sealed trait of all possible case classes, the root sealed trait also has many other sealed traits who extends it at different levels on the hierarchy.

It seems actually the code in decode.scala is not valid, since actually the subtypes of ctx in dispatch function also contains sealed traits, which are "CallByNeed", so if we do "ctx.subtypes.find(_.typeName.full == name).get" and if the case class that we want to find is actually one of the subtype of a sealed trait which is "CallByNeed" we cannot find the case class since it is not in subtypesArray.

I think it will be beneficial if we can somehow expose the names of all case class subtypes of a root sealed trait so that "ctx.subtypes.find(_.typeName.full == name).get" can be a valid check ?

gaoxinyang avatar Jul 22 '19 09:07 gaoxinyang

Just to make sure I understand (additionally, as I don't remember the exact behavior), does ctx.subtypes currently give you the immediate subtypes of the sealed trait (regardless of whether they're traits or case classes), and you would prefer it to give you all the case-class and case-object descendants?

I think that would be desirable, if so! And it shouldn't be too difficult to do.

propensive avatar Jul 22 '19 10:07 propensive

Hi, thanks for the reply.

It actually gives a mix of sealed traits and case classes of its descendants given a complex type hierarchy, for example, in the following hierarchy, (upper case is sealed trait (A, B, C, D) and lower case is case class(object) (x, e, f, g, h,i), in ctx.subtypes when applying dispatch function on A it may give me an array of [e, f, C, D, x].

                              A 
                         /   |    |   \
                       B    C     D     x
                     /  \   |    / \
                   e    f   g   h  i

I will try to make a simple working example to show the above case later.

gaoxinyang avatar Jul 22 '19 11:07 gaoxinyang

Thank you for the explanation!

I'm just wondering about the the subtypes array in your example. Do you know the reason why the array contains e and f (and not B), but also contains C and D while not including g, h or i? Are some of the traits not explicity sealed?

propensive avatar Jul 22 '19 14:07 propensive

I have created an example to reproduce the issue: https://github.com/gaoxinyang/magnolia-subtypes/tree/master/src/main/scala/com/example/magnolia

run application.scala firstly, you will get a list of subtypes of sealed trait Root: List(org.example.magnolia.A.A1, org.example.magnolia.A.A2, org.example.magnolia.B.CCC1, org.example.magnolia.B.CCC2, org.example.magnolia.C.CC1, org.example.magnolia.C.CC2, org.example.magnolia.C.CC3, org.example.magnolia.C.C1, org.example.magnolia.C.C2, org.example.magnolia.C.C3, org.example.magnolia.B.Root1), which is expected.

Then go to codec.scala, remove the 4 imports from line 38 to line 41, then run application.scala again, you will get subtypes of Root as List(org.example.magnolia.A.A1, org.example.magnolia.A.A2, org.example.magnolia.C.C, org.example.magnolia.B.Root1), in which org.example.magnolia.C.C is a sealed trait

gaoxinyang avatar Aug 20 '19 14:08 gaoxinyang

any thoughts ?

gaoxinyang avatar Sep 02 '19 09:09 gaoxinyang

@gaoxinyang code from the repo do not compile since 1.16.0. Any chance you could update the example? Maybe I could help with this problem :)

BTW Thanks for making a minimal reproducible example. I wish more people would report issues in that way 🙇

lemastero avatar Sep 28 '20 17:09 lemastero