Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

problem with sum type and focus #1329

Closed
mtumilowicz opened this issue Dec 4, 2022 · 1 comment
Closed

problem with sum type and focus #1329

mtumilowicz opened this issue Dec 4, 2022 · 1 comment

Comments

@mtumilowicz
Copy link

mtumilowicz commented Dec 4, 2022

libs

I am using newest monocle

"dev.optics" %% "monocle-core" % "3.1.0",
"dev.optics" %% "monocle-macro" % "3.1.0",

with single import

import monocle.syntax.all._

and scala 2.13.10

problem

I would like to change email when PaymentMethod is PayPal (equivalent of copy)

val modified = user.copy(paymentMethod = user.paymentMethod match {
  case PayPal(_) => PayPal(newEmail)
  case dc@DebitCard(_,_,_) => dc
})

with quicklens I do simply

user.modify(_.paymentMethod.when[PayPal].email).setTo(newEmail)

and everything works, I would like to have something similar with monocle

code

case class User(name: String, paymentMethod: PaymentMethod)

sealed trait PaymentMethod
object PaymentMethod {
  case class PayPal(email: String) extends PaymentMethod

  case class DebitCard(
                        cardNumber: String,
                        expirationDate: YearMonth,
                        securityCode: Int
                      ) extends PaymentMethod
}

first try:

user.focus(_.paymentMethod.as[PayPal].email).replace(newEmail)

compilation error

value as is not a member of shared.user.PaymentMethod

another try:

user.focus(_.paymentMethod.focus().as[PayPal].email).replace(newEmail)

I get compilation error

value email is not a member of monocle.AppliedPrism[shared.user.PaymentMethod,shared.user.PaymentMethod.PayPal]

when I do something like this

val result: PaymentMethod = user
  .focus(_.paymentMethod.focus().as[PayPal].modify(_.focus(_.email).replace(newEmail)))
  .get

I get PaymentMethod as a return instead of User

however when I create everything by myself I get what I need

val newEmail = "[email protected]"
val setPaymentMethod = GenLens[User](_.paymentMethod)
val setPayPalEmail = Prism.partial[PaymentMethod, String]{case PayPal(x) => x}(PayPal)
val updatePayPalEmail = setPaymentMethod andThen setPayPalEmail
val result: User = updatePayPalEmail.replace(newEmail)(user)

how to do the same with focus?

@julien-truffaut
Copy link
Member

@machisuji you would need to be using scala 3 to generate this optic.

Focus in scala 2 is much more limited. You can only using to generate lenses for fields inside a case class.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants