Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Repo info
Activity
Soren
@srnb_gitlab
  def transformObjectKeys(obj: JsonObject, f: String => String): JsonObject =
    JsonObject.fromIterable(
      obj.toList.map {
        case (k, v) => f(k) -> v
      }
    )
  def transformKeys(json: Json, f: String => String): Trampoline[Json] =
    json.arrayOrObject(
      Trampoline.done(json),
      _.traverse((j: Json) => Trampoline.defer(transformKeys(j, f))).map(Json.fromValues(_)),
      transformObjectKeys(_, f).traverse(obj => Trampoline.defer(transformKeys(obj, f))).map(Json.fromJsonObject)
    )
This is the code I'm attempting to use
Luka Jacobowitz
@LukaJCB
traverse doesn’t quite fit your bill, it has the following signature: F[G[A]] => G[F[A]], your Vector[Json] doesn’t fit, because Json does not take a type parameter
What is it you actually want to do?
ah okay, so you’re traversing with Trampoline[Json]
Andrew Valencik
@valencik
Is there existing work/literature I could poke around to learn about dealing with Tree structures that have lots of different sub types? In particular, SQL parse trees. A query can have many SelectItems and many Relations and eventually many Expression, but a Expression can also contain a query itself.
Jakub Kozłowski
@kubukoz
sounds a bit like fixed-point data types
from what I heard
Luka Jacobowitz
@LukaJCB
Recursion schemes
Jakub Kozłowski
@kubukoz
or that, yeah
Andrew Valencik
@valencik
Oh interesting. I know nothing about recursion schemes. I don't even know if "are they supported in cats?" is a reasonable question
Ghost
@ghost~55118a7f15522ed4b3ddbe95
you need multirec for that
object Fix2 {
  type Fix2_1[F1[_, _], F2[_, _]]
  type Fix2_2[F1[_, _], F2[_, _]]

  final class Subst[F1[_, _], F2[_, _]] {
    type Apply[H[_[_, _], _[_, _]]]  = H[F1, F2]
    type ApplyF[H[_, _]] = H[Apply[Fix2_1], Apply[Fix2_2]]

    def _1[H[_]](f: H[Apply[Fix2_1]]): H[ApplyF[F1]] = f.asInstanceOf[H[ApplyF[F1]]]
    def _2[H[_]](f: H[Apply[Fix2_2]]): H[ApplyF[F2]] = f.asInstanceOf[H[ApplyF[F2]]]
  }

  private[this] val _subst = new Subst[Any, Any]
  def subst[F1[_, _], F2[_, _]]: Subst[F1, F2] = _subst.asInstanceOf[Subst[F1, F2]]
}
I don't think it will be pleasant in Scala, but who knows
Andrew Valencik
@valencik
Shucks. So not much in the cats ecosystem then? I see matryoshka is decidedly scalaz again. Not sure how much that matters.
Ghost
@ghost~55118a7f15522ed4b3ddbe95
You won't be able to use matryoshka in your particular case anyway
when you have multiple mutually recursive types you need multirec
but, learning recursion schemes is a good investment regardless :smile:
Andrew Valencik
@valencik
Just want to make sure I understand. The fact that queries have expressions and expressions have expressions and queries makes this a type with multiple mutually recursive types? And furthermore, matryoshka does not support multiple mutually recursive types, but multirec does?
Ghost
@ghost~55118a7f15522ed4b3ddbe95
final case class Query(e: Expr)
final case class Expr(e: Query)

// this will work with matryoshka
// can recurse only over one part at a time
final case class QueryF[Q](e: Expr[Q])
final case class Expr[Q](e: Q)

// this requires something like multirec
final case class QueryF[Q, E](e: E)
final case class ExprF[Q, E](e: Q)
Andrew Valencik
@valencik
ahhhh i get it now. thank you, super helpful
So, given that multirec is a haskell library and I'm in Scala, looks like I can't define recursive schemes for this data type. Am I going to be able to use any other type classes from cats at all?
Ghost
@ghost~55118a7f15522ed4b3ddbe95
mm absolutely
Soren
@srnb_gitlab
@LukaJCB so how should I do this?
I'm running regex replacements to transform underscored_keys into camelCasedKeys and back
Jakub Kozłowski
@kubukoz
@srnb_gitlab just so you know, you can configure circe to use a particular naming strategy when decoding/encoding
like using camelcased keys or underscored keys
see https://circe.github.io/circe/codecs/custom-codecs.html#custom-key-mappings-via-annotations
e.g. implicit val config: Configuration = Configuration.default.withSnakeCaseMemberNames with semiauto decoding/encoding should work
and you could provide your own Configuration with a custom key renaming strategy. Probably better than manually traversing the jsons
Manuel Cueto
@manuelcueto
I went to a meetup where a guy explained a way to construct actors with cats-effects . Unfortunately I’m on holidays and i have his github on a notebook somewhere at home
Martin Grigorov
@martin-g
aren't all actors reactive ? they react on messages/events/signals
Martin Grigorov
@martin-g
both videos show how to create really minimalistic actors
Martin Grigorov
@martin-g
spend some more time on it! it will be useful to compare the alternatives
Martin Grigorov
@martin-g
I agree on both observations!
anyway, I think you should tell your boss what you have found. Explain what you have understood and what you haven't. And decide which one to dig deeper
Piotr Gawryś
@Avasil
FYI @turt13 you can easily cover those use cases using cats.effect.IO or monix.eval.Task too
Rob Norris
@tpolecat
Why does your boss want you to use actors? Maybe chase that down a bit.
Matthew de Detrich
@mdedetrich
If you need to seperate your business logic across multiple nodes, then there may be a case for using actors. Otherwise you probably don’t need them.
Rob Norris
@tpolecat
It’s like saying fix my car, be sure to use a band saw.
In that it would probably make sense to ask some follow up questions.
Soren
@srnb_gitlab
@kubukoz so like this?
  val keyCorrectionReg: Regex = """_([a-z])""".r
  val keyDeCorrectionReg: Regex = """([A-Z])""".r
  implicit val config: Configuration = Configuration.default.withSnakeCaseMemberNames.copy(transformMemberNames = s => {
    keyDeCorrectionReg.replaceAllIn(s, m => "_" + m.group(1).toLowerCase)
  })
Jakub Kozłowski
@kubukoz
I'm not sure what exactly you want to do
looks like keyCorrectionReg isn't used in this
it'd be best if you could provide an example of
  1. the JSON that comes in
  2. the case class you want to have after decoding
Soren
@srnb_gitlab
We're solving this in the circe/circe room now, but I need a solution that works for both encoding thisCase => this_case and decoding this_case => thisCase