Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Repo info
Activity
  • Jan 29 20:39

    joroKr21 on main

    Update sbt-scalajs, scalajs-com… (compare)

  • Jan 29 20:39
    joroKr21 closed #1297
  • Jan 29 20:31
    joroKr21 synchronize #1297
  • Jan 29 20:30

    joroKr21 on main

    Update scala-parser-combinators… (compare)

  • Jan 29 20:30
    joroKr21 closed #1298
  • Jan 29 19:41
    joroKr21 synchronize #1298
  • Jan 29 19:41

    joroKr21 on main

    Update junit-plugin, junit-runt… (compare)

  • Jan 29 19:41
    joroKr21 closed #1299
  • Jan 29 19:14
    scala-steward opened #1299
  • Jan 27 20:05
    scala-steward opened #1298
  • Jan 27 20:05
    scala-steward opened #1297
  • Jan 07 17:55

    joroKr21 on main

    Update sbt to 1.8.2 (#1296) (compare)

  • Jan 07 17:55
    joroKr21 closed #1296
  • Jan 07 00:30
    DmytroMitin commented #1285
  • Jan 05 17:36
    scala-steward opened #1296
  • Dec 28 2022 14:35

    joroKr21 on main

    Fixed typo (#1295) (compare)

  • Dec 28 2022 14:35
    joroKr21 closed #1295
  • Dec 28 2022 07:13
    windymelt opened #1295
  • Dec 15 2022 20:59

    joroKr21 on main

    Update slf4j-nop to 2.0.6 (#129… (compare)

  • Dec 15 2022 20:59
    joroKr21 closed #1294
Fabio Labella
@SystemFw
then move the implicit deriveMsgPack into the companion object of an example case class and see if it still works
I'm not 100% sure of the precedence
but if it does work
then you can try having a trait just to declare the implicit for your users
again, I'll need to double check
actually, I'll try and write an example with an empty typeclass to see if my approach makes sense or not (it might not)
might have some time later on tonight, perhaps
I'll ping you if I manage :)
Andrew Roberts
@aroberts
ok, awesome :)
I’ll share as well if I get my indirection wired up
Fabio Labella
@SystemFw
:+1:
Fabio Labella
@SystemFw
@aroberts This is what I have in mind
object Module {
  import shapeless._

  sealed trait Decode[A] {
    def decode(s: String): Option[A]
  }
  object Decode {
    def dummy[A]: Decode[A] = new Decode[A] {
      def decode(s: String) = Option.empty[A]
    }

    def apply[A](implicit decoder: Decode[A]): Decode[A] =
      decoder

    implicit def strings: Decode[String] = dummy[String]
    implicit def bools: Decode[Boolean] = dummy[Boolean]
    implicit def ints: Decode[Int] = dummy[Int]

    implicit def hnil: Decode[HNil] = dummy[HNil]
    implicit def hcons[H: Decode, T <: HList: Decode]: Decode[H :: T] =
      dummy[H :: T]

    implicit def cnil: Decode[CNil] = dummy[CNil]
    implicit def ccons[H: Decode, T <: Coproduct: Decode]: Decode[H :+: T] =
      dummy[H :+: T]  
  }

  trait DeriveDecoder[F] {
      implicit def generics[A <: F, R](implicit gen: Generic.Aux[A, R],
                                decoder: Decode[R]): Decode[A] = Decode.dummy[A]
  }
}

sealed trait A
case class B(s: String, i: Int) extends A
case class C(b: Boolean) extends A
object A extends Module.DeriveDecoder[A]

sealed trait A1
case class B1(s: String, i: Int) extends A1
case class C1(b: Boolean) extends A1

object Test {
  import shapeless.test._
  val a = Module.Decode[A]
  val b = illTyped("Module.Decode[A1]")
  // code compiles
}
Note the zero imports required at call site
Fabio Labella
@SystemFw
another way of doing it would be to put generics back into Decode, but add a dummy typeclass to its implicit arguments, and then have DeriveDecoder[A] derive an instance of said dummy typeclass for all subtypes of A
this would probably be my preferred solution actually
like this
object Module {
  import shapeless._

  sealed trait Decode[A] {
    def decode(s: String): Option[A]
  }
  object Decode {
    def dummy[A]: Decode[A] = new Decode[A] {
      def decode(s: String) = Option.empty[A]
    }

    def apply[A](implicit decoder: Decode[A]): Decode[A] =
      decoder

    implicit def strings: Decode[String] = dummy[String]
    implicit def bools: Decode[Boolean] = dummy[Boolean]
    implicit def ints: Decode[Int] = dummy[Int]

    implicit def hnil: Decode[HNil] = dummy[HNil]
    implicit def hcons[H: Decode, T <: HList: Decode]: Decode[H :: T] =
      dummy[H :: T]

    implicit def cnil: Decode[CNil] = dummy[CNil]
    implicit def ccons[H: Decode, T <: Coproduct: Decode]: Decode[H :+: T] =
      dummy[H :+: T]

    implicit def generics[A, R](implicit gen: Generic.Aux[A, R],
                                decoder: Decode[R], opt: OptIn[A]): Decode[A] = Decode.dummy[A]
  }

  sealed trait OptIn[A]
  object OptIn {
    def instance[A]: OptIn[A] = new OptIn[A] {}
  }

  trait DeriveDecoder[F] {
      implicit def optIn[A <: F] = OptIn.instance[A]
  }
}

sealed trait A
case class B(s: String, i: Int) extends A
case class C(b: Boolean) extends A
object A extends Module.DeriveDecoder[A]

sealed trait A1
case class B1(s: String, i: Int) extends A1
case class C1(b: Boolean) extends A1

object Test {
  import shapeless.test._
  val a = Module.Decode[A]
  val b = illTyped("Module.Decode[A1]")
  // code compiles
}
David Hoyt
@davidhoyt
hello -- looking for a way to get the depth of nested HLists. e.g.: String :: (Int :: (Long :: HNil) :: HNil) :: HNil. any recommended approach?
i really only need to know if I'm nested or not. this is for automatic type class derivation btw.
generally speaking, I want to take nested case classes and spit out a flattened list of field=value. e.g.:
case class Foo(a: String, b: Bar)
case class Bar(c: Int, d: Baz)
case class Baz(e: Long)

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

val flattened: String = ??? // Should be "a=A c=1 e=2"
David Hoyt
@davidhoyt
I've started by looking at LabelledGeneric and can iterate over fields and values, but I haven't thus far worked out how to successfully determine if I'm nested
Andrew Roberts
@aroberts
(operates on tuples but hlist is isomorphic to tuple)
Fabio Labella
@SystemFw
@davidhoyt the problem with what you want to do
is not flattening, that's easy
actually, I take it back. Flattening HLists is easy
flattening Products has additional difficulties, let me give it a try
Andrew Roberts
@aroberts
@SystemFw I think I took the same approach, just organized a little bit differently
Fabio Labella
@SystemFw
:+1:
Andrew Roberts
@aroberts
the only think I’m missing is deriving the freaking cases from within the coproduct derived codec
Fabio Labella
@SystemFw
what I like about OptIn is that I can envision it being expanded with options to customise the derivation, using the same scheme
@aroberts how are you encoding the coproduct?
I mean the mapping Coproduct => Index
what is it?
Andrew Roberts
@aroberts
I created a special-case encoding instance that’s index-aware
Fabio Labella
@SystemFw
yeah that's not what I mean
Andrew Roberts
@aroberts
trait MsgpackIndexed[A] extends Msgpack[A] {
  private val si = Serialize[Int]
  val defaultIndex = 0

  def pack(v: A) = packIndexed(defaultIndex, v).flatMap((packWithIndex _).tupled)
  def unpack(v: MessagePack) = v match {
    case MFixArray(Vector(i, m)) => si.unpack(i).flatMap(unpackIndexed(_, m))
    case _ => Attempt.failure(Err(s"Couldn't unpack indexed messagepack from $v"))
  }

  def packIndexed(index: Int, v: A): Attempt[(Int, MessagePack)]
  def unpackIndexed(index: Int, v:  MessagePack): Attempt[A]

  private def packWithIndex(index: Int, payload: MessagePack): Attempt[MessagePack] =
    si.pack(index).map(packed => MFixArray(Vector(packed, payload)))
}
Fabio Labella
@SystemFw
ah ok wait
nope, that's not what I mean :)
but rather, given an ADT coproduct, how does the numbering work?
Andrew Roberts
@aroberts
This message was deleted
Fabio Labella
@SystemFw
e.g. the first case gets 0, and so on
Andrew Roberts
@aroberts
  implicit val serializeCNil: MsgpackIndexed[CNil] = new MsgpackIndexed[CNil] {
    def packIndexed(index: Int, v: CNil) = Attempt.failure(Err(s"CNil can't be packed: $v"))
    def unpackIndexed(index: Int, v: MessagePack) = Attempt.failure(Err(s"CNil can't be unpacked: $v"))
  }

  implicit def serializeCCons[H, T <: Coproduct](implicit
      hSer: Msgpack[H],
      tSer: MsgpackIndexed[T]
  ): MsgpackIndexed[H :+: T] = new MsgpackIndexed[H :+: T] {
    def packIndexed(index: Int, v: H :+: T) = v match {
      case Inl(h) => hSer.pack(h).map((index, _))
      case Inr(t) => tSer.packIndexed(index + 1, t)
    }

    def unpackIndexed(index: Int, v: MessagePack) = index match {
      case 0 => hSer.unpack(v).map(Inl(_))
      case n => tSer.unpackIndexed(n - 1, v).map(Inr(_))
    }
  }
Is that what you mean? it’s basically a count of how many Inr cases are processed before an Inl instance is encountered
Fabio Labella
@SystemFw
yes
what's the problem with it?
Andrew Roberts
@aroberts
nothing, as far as I can tell
Fabio Labella
@SystemFw
ah
Andrew Roberts
@aroberts
the issue is a derivation problem