Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Repo info
Activity
  • 11:38
    nicolasstucki synchronize #1186
  • 11:34
    nicolasstucki synchronize #1186
  • 11:34
    nicolasstucki ready_for_review #1186
  • 08:15
    nicolasstucki commented #1186
  • 08:13
    nicolasstucki opened #1186
  • Aug 02 02:31
    japgolly synchronize #1185
  • Aug 02 02:28
    japgolly opened #1185
  • Aug 02 00:57
    japgolly commented #1043
  • Aug 02 00:51
    kenbot commented #1043
  • Aug 02 00:49
    japgolly commented #1043
  • Aug 02 00:44
    japgolly commented #1181
  • Aug 01 02:31
    kenbot commented #1043
  • Jul 31 06:34
    julien-truffaut commented #1043
  • Jul 31 04:31
    japgolly commented #1043
  • Jul 30 10:56
    scala-steward synchronize #1156
  • Jul 30 08:42

    julien-truffaut on gh-pages

    Deploy website Deploy website … (compare)

  • Jul 30 08:36

    julien-truffaut on mima-update

    (compare)

  • Jul 30 08:36

    julien-truffaut on master

    update mima settings (#1180) (compare)

  • Jul 30 08:36
    julien-truffaut closed #1180
  • Jul 29 19:40
    julien-truffaut synchronize #1180
Julien Truffaut
@julien-truffaut
if you use the latest version of Monocle, you can use .filter instead of a custom Prism
fromscalatohaskell
@fromscalatohaskell_gitlab
thanks!!! thats a bit nicer
any other tips?
Julien Truffaut
@julien-truffaut
I am not sure why you start with tree.leaves.map {
fromscalatohaskell
@fromscalatohaskell_gitlab
I need to return list of setters for parts of subtree essentially
Julien Truffaut
@julien-truffaut
It seems you could do
Focus[Tree](_.leaves).filter(_.num % 2 == 0)
fromscalatohaskell
@fromscalatohaskell_gitlab
in my real app i have analyser that checks it against some outside rules and returns List(Rule, Setter)
Julien Truffaut
@julien-truffaut
k
fromscalatohaskell
@fromscalatohaskell_gitlab
im not saying there's not better way, that's why I'm asking experts :)
I essentially recrusively validate the rules and zoom into the structure to build up "which rule violated which part of the structure, and setter to change it"
Julien Truffaut
@julien-truffaut
Monocle 3.0.0-RC2 is released with a new organisation (dev.optics)
https://twitter.com/JulienTruffaut/status/1399663531772022785
fromscalatohaskell
@fromscalatohaskell_gitlab
fantastic
Igal Tabachnik
@hmemcpy

Good evening all!

I was wondering how can I improve upon this manual thing I'm doing now?
Suppose I have a case class Person(name: String, age: Int). I receive a PATCH request, containing optional fields that may have changed. What I'm currently doing is manually building a bunch of Person => Person functions, either copying over the new value or returning the given person unchanged, then applying all those "patch" functions one after the other to the initial person.

Surely there's a better way :slight_smile:

case class PatchPersonRequest(name: Option[String], age: Option[Int])

val request = PatchPersonRequest(...)

val patchName: Person => Person = request.name.fold[Person => Person](identity)(n => p => p.copy(name = n))
val patchAge: Person => Person = request.age.fold[Person => Person](identity)(a => p => p.copy(age = a))
...

val updatedPerson = Patch.merge(
    person,
    patchName,
    patchAge
    ...
)

I'm using monocle to update deeply nested properties of person, but even then this is manual and repetitive... and boilerplatey :(

Patch.merge does a foldLeft over the Seq[A => A], applying it to the initial A...
Julien Truffaut
@julien-truffaut
you can improve the setting part in monocle 3 with n => p.focus(_.name).replace(n)
not shorter though
instead of doing fold maybe you could use foldMapM or other variants of foldMap
it is mostly to get rid of identity
Igal Tabachnik
@hmemcpy
Thanks! I was told that Chimney handles this exact scenario! https://scalalandio.github.io/chimney/patchers/options-handling.html
Julien Truffaut
@julien-truffaut
Nice
Igal Tabachnik
@hmemcpy
But I wonder if this could also be a good fit for an optics library.
Shah Saraei
@ShahOdin

I have a product type with optional types such as

case class Foo(bar1: Option[Bar1], bar2: Option[Bar2], bar3: Option[Bar3])

I will have a list of optional bar[i]s and I want to optionally modify my Foo instance with them.

as it stands I have to repeat _.focus.replace for each param. is there a way of abstracting it out? I tried doing that with something like:

def updateWith[T](f: Foo => Option[T]): ???

but I get:

Illegal field reference f; please use _.field1.field2... instead

is there a way of marking updateWith somehow to make this go away?

Julien Truffaut
@julien-truffaut
in Scala 3, you can do _.focus(_.bar1.some.xxx)
in Scala 2, you can do _.focus(_.bar1).some.andThen(Focus[Bar1](_.xxx))
Shah Saraei
@ShahOdin

Thanks Julien. I think you misunderstood my issue: I don't care about the nested types in BarXtypes here. I have maybeValues which I would like to update my model with, if they were Some() initially I wanted to do something like:

List(
  maybeBar1.map(updateWith),
  maybeBar2.map(updateWith)
).reduceLeft(..)

with the updateWith being responsible for the fold needed but then I faced the problem I described.

but I just realised I would be equally happy with something like:

foo
  .focus(_.bar1).replaceIfSome(maybeBar1)
  .focus(_.bar2).replaceIfSome(maybeBar2)

with the function looking something like:

  implicit class AppliedLensOps[A, C](lens: AppliedLens[A, Option[C]]) {
    def replaceIfSome(maybe: Option[C]): A = maybe.fold(
      lens.value
    )( w =>
      lens.replace(w.some)
    )
  }

is there a more generic way of doing this? :thinking

Julien Truffaut
@julien-truffaut
ah then, you can do
foo
  .focus(_.bar1).some.replace(maybeBar1)
  .focus(_.bar2).some.replace(maybeBar2)
Shah Saraei
@ShahOdin

tried above with Scala 2, I get:

found : Option[Bar1]
required: Bar1
.focus(.bar1).some.replace(maybeBar1)

Julien Truffaut
@julien-truffaut
maybeBar1 needs to be a Bar1
or do you want to set it to None if it is a Some?
Shah Saraei
@ShahOdin
see replaceIfSome impl above. I want to leave Foo alone if maybeBar is None, but replace its bar1 value if it's Some(_)
Julien Truffaut
@julien-truffaut
ah ok, you're right. I thought the if None / if Some logic was based on the field of Foo, but it is in fact based on maybeBar1
I should read more carefully next time
Shah Saraei
@ShahOdin
;) I guess it makes sense for replaceIfSome not to be hard-coded in the lib itself since as you say, the behaviour is not based on the Foo itself.
Julien Truffaut
@julien-truffaut
indeed
Ken Scambler
@kenbot
replace already only sets the value if it is present - this is why we renamed it from set, "replace" is supposed to suggest there's already a value
I'm not sure if you want us to second-guess your structure (sorry if not!), but a case class with fully optional members is often better represented by a Map
Shah Saraei
@ShahOdin

@julien-truffaut I have the same problem as here: https://stackoverflow.com/a/42668525/9199853 I tried to replicate your answer with the updated API:

  import monocle.macros.GenIso
  case class Alpha(text: String = "content")
  case class Beta(alpha: Alpha = Alpha())
  case class Gamma(beta: Option[Beta])
  val navigateToText = GenIso[Gamma, Option[Beta]]
    .andThen(GenIso[Beta, Alpha].asPrism.below[Option])
    .andThen(GenIso[Alpha, String].asPrism.below[Option])

it compiles. but if I add another field to Gamma, say: maybeI: Option[Int] it complains of:

Found several case class accessor for Gamma, Gamma needs to be a case class with a single accessor.

which makes sense now that I think about it. is there a way of solving the more generalised problem?

Shah Saraei
@ShahOdin
ok nvm, in general Beta might have multiple fields and with Gamme(None) it's not clear how we can create a Beta out of the blue which happens to have a nested Alpha. are there abstractions here that we could use to solve this problem?
Jan Bracker
@jbracker
What is the right monocle abstraction for an optional extractor aka "S => Option[A]" (an unapply method)? At first I thought I wanted a Prism or an Optional but both of those require a "reverse" route which I don't have. What I need is a Getter that delivers Option[A] instead of A. But if I use Getter[S, Option[A]] I need to flatten all of my results. Or is this something I should do with a special kind of Fold? I am unsure how the Monoid would work in that case...
Jan Bracker
@jbracker
Oh, I suppose this should work? override def foldMap[M](f: A => M)(s: S)(implicit monoid: Monoid[M]): M = unapply(s).fold(monoid.empty)(f)where unapply: S => Option[A]
Jan Bracker
@jbracker
Why are there no FoldLaws?
Julien Truffaut
@julien-truffaut
Foldable as no laws, I guess it could have some laws to check consistency between methods but that's it
Julien Truffaut
@julien-truffaut
felher
@felher

Hey folks :)

I'm trying to use monocle 3.0.0 with ScalaJS and Scala 3.0, but I'm getting Referring to non-existent class monocle.syntax.AppliedPLens$ as an error during fastLinkJS. Has anyone seen that before?

Julien Truffaut
@julien-truffaut
hey, could it be possible you have multiple monocle version in your path? (we renamed the organsiation)
felher
@felher
@julien-truffaut Sorry for the noise, I was just being dumb :)
But, for posterity, if someone makes the same mistake I did: Make sure, when using scalajs, that you have three, not two %%% (goes without saying, but I somehow missed it)
Julien Truffaut
@julien-truffaut
np :)
felher
@felher
Hey again ;)
Can I use focus to zoom into an index of list? Like person.focus(_.addresses(0)) ?
Wow, again. I found it... index. Sorry for the noise again. I have to be careful that doesn't become a running gag.
Ken Scambler
@kenbot
No worries, ask away! I'm glad it was discoverable