Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Repo info
Activity
  • May 09 21:03
    joroKr21 synchronize #1240
  • Apr 07 16:55

    joroKr21 on main

    Update sbt-mima-plugin to 1.1.0 Merge pull request #1258 from s… (compare)

  • Apr 07 16:55
    joroKr21 closed #1258
  • Apr 07 16:47
    scala-steward opened #1258
  • Apr 05 06:02

    joroKr21 on main

    Update sbt-scalajs, scalajs-com… Merge pull request #1257 from s… (compare)

  • Apr 05 06:02
    joroKr21 closed #1257
  • Apr 05 02:57
    scala-steward opened #1257
  • Mar 27 15:42

    joroKr21 on v2.3.9

    (compare)

  • Mar 26 20:08
    joroKr21 closed #1254
  • Mar 26 20:08
    joroKr21 commented #1254
  • Mar 26 20:05

    joroKr21 on 2.3

    When case class has custom unap… Merge pull request #1256 from j… (compare)

  • Mar 26 20:05
    joroKr21 closed #1256
  • Mar 26 19:29
    joroKr21 synchronize #1256
  • Mar 26 18:51
    joroKr21 labeled #1256
  • Mar 26 18:51
    joroKr21 labeled #1256
  • Mar 26 18:51
    joroKr21 assigned #1256
  • Mar 26 18:51
    joroKr21 opened #1256
  • Mar 26 17:45

    joroKr21 on main

    When case class has custom unap… Merge pull request #1255 from j… (compare)

  • Mar 26 17:45
    joroKr21 closed #1255
  • Mar 26 17:45
    joroKr21 closed #1059
David Hoyt
@davidhoyt
really appreciate your help
Ryan Williams
@ryan-williams

OT: can i get a Generic for a trait with only abstract fields? e.g. with a structure like this:

trait Foo { def a: A; def b: B; def c: C }
trait Bar extends Foo { def d: D }
trait Baz extends Foo { def e: E }

I want to be able to get Generics for Foo/Bar/Baz.

The context is that I'm trying to have multiple classes/traits share a set of fields while also being able to get a Generic for them, without having to repeat all the fields everywhere. traits can be composed to allow this but but classes/fields/ctor-args can't. cf. https://github.com/alexarchambault/case-app/issues/58#issuecomment-313799457

i'm considering trying to write a macro (annotation?) to do it. i guess some detail on the macro that shapeless uses to get Generics for case classes would be useful too; iirc it hangs off of the existence of a case class's apply method?
Fabio Labella
@SystemFw
@davidhoyt Sorry, had to go away. I have a Poly that flattens arbitrarily nested case classes , preserving the names of the fields in a type akin to a LabelledGeneric#Repr
  case class Foo(a: String, b: Bar)
  case class Bar(c: Int, d: Baz)
  case class Baz(e: Long)

  val v = Foo("A", Bar(1, Baz(2)))

  def a = flatten(v)
  res1: shapeless.::[String with shapeless.labelled.KeyTag[Symbol with shapeless.tag.Tagged[String("a")],String],shapeless.::[Int with shapeless.labelled.KeyTag[Symbol with shapeless.tag.Tagged[String("c")],Int],shapeless.::[Long with shapeless.labelled.KeyTag[Symbol with shapeless.tag.Tagged[String("e")],Long],shapeless.HNil]]] = 
    A :: 1 :: 2 :: HNil
Fabio Labella
@SystemFw
Question: given a Poly f, I can implicitly ask for an instance of that poly for type parameter A by implicit ev: Case[A, f.type].
Provided the types line up, I can compose f with another poly g via object c extends Compose(f, g). How do I implicitly ask for an instance of the composed poly for type parameter A?
Fabio Labella
@SystemFw
nvm, figured it out (Case[c.type, A :: HNil])
@davidhoyt solved it!
David Hoyt
@davidhoyt
@SystemFw great thanks -- i just read all of dave gurnell's book on shapeless :)
@SystemFw please share!
Fabio Labella
@SystemFw
I did it with Polys to learn something different, I think it would have actually been easier (but more verbose), to figure out with just custom typeclasses, but here you go:
  import shapeless._, ops.hlist._, poly._, labelled._

  trait Describe[A] {
    def apply(a: A): String
  }
  object Describe {
    def apply[A](a: A)(implicit ev: Describe[A]) = ev(a).dropRight(2)

    implicit def all[A](
        implicit f: Case.Aux[body.type, A :: HNil, String]): Describe[A] =
      new Describe[A] {
        def apply(a: A) = f.apply(a)
      }
    object body extends Compose(describer, flatten)

    object describer extends LowPrioDescriber {
      implicit def all[H <: HList](
          implicit fm: MapFolder[H, String, describer.type]) =
        at[H](x => fm(x, "", _ + _))
    }
    trait LowPrioDescriber extends Poly1 {
      implicit def base[K <: Symbol, V](implicit key: Witness.Aux[K]) =
        at[FieldType[K, V]](x => s"${key.value.name} = ${x.toString}, ")
    }

    object flatten extends LowPrioFlatten {
      implicit def hlists[H <: HList](
          implicit fm: Lazy[FlatMapper[flatten.type, H]]) =
        at[H](x => fm.value(x))

      implicit def kv[K, V, R](implicit gen: LabelledGeneric.Aux[V, R],
                               rec: Lazy[Case1[flatten.type, R]]) =
        at[FieldType[K, V]](x => rec.value(gen.to(x)))

      implicit def prods[A, R <: HList](
          implicit gen: LabelledGeneric.Aux[A, R],
          rec: Lazy[Case1[flatten.type, R]]) =
        at[A](x => rec.value(gen.to(x)))
    }
    trait LowPrioFlatten extends Poly1 {
      implicit def all[A] = at[A](x => x :: HNil)
    }
  }
example:
  case class Foo(a: String, b: Bar)
  case class Bar(c: Int, d: Baz)
  case class Baz(e: Long)

  val v = Foo("A", Bar(1, Baz(2)))

  def c = Describe(v)
 // res1: String = a = A, c = 1, e = 2
I'll go create a gist
David Hoyt
@davidhoyt
now to parse all of this to see if I can follow it...
Fabio Labella
@SystemFw
since someone else asked this several weeks ago, but I didn't have the time to fully solve it then
David Hoyt
@davidhoyt
this preserves the declaration order, right?
Fabio Labella
@SystemFw
what do you mean?
I tested it with the example you gave me
can't you see it? (gitter is weird sometimes)
one thing that I'm not too sure about
what happens with things like List
David Hoyt
@davidhoyt
e.g.:
case class Foo(a: String, b: Int, c: Bar)
case class Bar(d: Baz, e: Int)
case class Baz(f: Long, g: String)

val v = Foo("A", 1, Bar(Baz(2, "G"), 3))

// a = A b = 1 f = 2 g = G e = 3
I actually don't care about preserving order, but bonus points if it does. I am inclined to think that it preserves it.
Fabio Labella
@SystemFw
res1: String = a = A, b = 1, f = 2, g = G, e = 3
that's the result
however, describer probably needs some modification, it doesn't compile if your case classes have Lists in them
but the basic idea is there
mm, no, there'a problem
but it's a problem with the whole idea, not with the implementation
what do you want the behaviour to be if your classes contain things like List Option, and in general, data types with alternatives?
David Hoyt
@davidhoyt
@SystemFw I would derive a type class for it. e.g.: https://scalafiddle.io/sf/8e8Kbup/0
@SystemFw in that fiddle i try to do just that but it doesn't work
Fabio Labella
@SystemFw
but what do you want the result to be? there's a very easy way to have it print "b = List(1,2)" in that case
David Hoyt
@davidhoyt
I don't think I'm following then -- I want the result to be whatever the type class decides
Fabio Labella
@SystemFw
now I'm not following :)
the basic problem is this: how do you distinguish between a Baz and a List?
also note that my solution was merely for the example at the beginning, if you want different strategies for unpacking different things you are probably better off moving away from the Poly towards a custom type class (even though you get to keep, with small adaptations, most of the code in the instances)
the reason for that is my approach first flattens, then describes
Fabio Labella
@SystemFw
(btw, to have it print List(1,2) just add <: HListto the R type parameter in kv)
if you want Lists to be printed differently, e.g. 1..2, add an instance to describer
David Hoyt
@davidhoyt
@SystemFw please see my fiddle here: https://scalafiddle.io/sf/8e8Kbup/1
it is not picking up and using forTraversable()
@SystemFw so I do want Lists to be printed differently which is why I added an implicit def to construct a type class for List[Int]. it should display lists as [1,2]
Fabio Labella
@SystemFw
the way my approach works, you don't write down any more instances for Describe
because Describe is not being resolved recursively
(you could do it that way, but you need to change my code first)
I can tweak it to accommodate your use case I think
so, iterables should be [1,2,3] and so on right? or [1] if they have one element
David Hoyt
@davidhoyt
@SystemFw it's supposed to be a type class so I could change the output by changing which implementation is implicitly available. my fiddle gives my default implementation.
Fabio Labella
@SystemFw
right (just a thing, if you have multiple implementations for the same type, it's not technically a type class)
anyway what you want can be done with my approach