Size: a a a

Scala User Group

2020 June 06

OS

Oleg Svechkarenko in Scala User Group
Спасибо
источник

СП

Саша Павлычев... in Scala User Group
Ребят, никто не слышал : Хорстман планирует выпустить 3 издание по Скале 3 для нетерпеливых ?
источник

AS

Alex Sh in Scala User Group
Народ, привет.
Можт кто-нть подсказать, умеет ли monocle автоматически выводить/генерировать линзы по типам?

Например есть что-то типа:
final case class UserName(value: String)
final case class Street(value: String)
final case class HouseNum(value: Int)
final case class Address(street: Street, num: HouseNum)
final case class User(name: UserName, address: Address)

и чтобы можно было просто написать:
val user = User(???, ???)
DeriveLens.set[User, HouseNum](HouseNum(100500))(user)

без необходимости прописывать все линзы вручную:
val address2street: Lens[Address, Street]  = GenLens[Address](_.street)
val address2house: Lens[Address, HouseNum] = GenLens[Address](_.num)
val user2name: Lens[User, UserName]        = GenLens[User](_.name)
val user2address: Lens[User, Address]      = GenLens[User](_.address)
val user2street: Lens[User, Street]        = user2address.composeLens(address2street)
val user2house: Lens[User, HouseNum]       = user2address.composeLens(address2house)
val name2value: Lens[UserName, String]     = GenLens[UserName](_.value)
источник

НМ

Никита Мязин... in Scala User Group
Alex Sh
Народ, привет.
Можт кто-нть подсказать, умеет ли monocle автоматически выводить/генерировать линзы по типам?

Например есть что-то типа:
final case class UserName(value: String)
final case class Street(value: String)
final case class HouseNum(value: Int)
final case class Address(street: Street, num: HouseNum)
final case class User(name: UserName, address: Address)

и чтобы можно было просто написать:
val user = User(???, ???)
DeriveLens.set[User, HouseNum](HouseNum(100500))(user)

без необходимости прописывать все линзы вручную:
val address2street: Lens[Address, Street]  = GenLens[Address](_.street)
val address2house: Lens[Address, HouseNum] = GenLens[Address](_.num)
val user2name: Lens[User, UserName]        = GenLens[User](_.name)
val user2address: Lens[User, Address]      = GenLens[User](_.address)
val user2street: Lens[User, Street]        = user2address.composeLens(address2street)
val user2house: Lens[User, HouseNum]       = user2address.composeLens(address2house)
val name2value: Lens[UserName, String]     = GenLens[UserName](_.value)
Это то что нужно?
источник

AS

Alex Sh in Scala User Group
Никита Мязин
Это то что нужно?
Нее... Не совсем.
Это похоже на Ad-Hoc определение линзы
john.lens(_.name).set("Mike")

Хочется, чтобы не надо было писать .lens(_.name)
источник

S

Simon in Scala User Group
Alex Sh
Нее... Не совсем.
Это похоже на Ad-Hoc определение линзы
john.lens(_.name).set("Mike")

Хочется, чтобы не надо было писать .lens(_.name)
GenLense[User](_.address.num)
источник

S

Simon in Scala User Group
это единственный вариант
источник

S

Simon in Scala User Group
По типам, конечно, можно что-то изобрести на основе shapeless линз, но мне жалко компилятор - ему будет тяжело
источник

AS

Alex Sh in Scala User Group
Simon
GenLense[User](_.address.num)
Опять не то.
Тут явно указывается путь до определенного поля.
Хочется, чтобы monocle сам вывел его во время компиляции исходя из начального типа User и конечного HouseNum
Хотя я не уверен, что такое в принципе возможно.

Но всё равно хочется. Иначе очень много boilerplate code получается на определение всех нужных линз
источник

AS

Alex Sh in Scala User Group
Simon
По типам, конечно, можно что-то изобрести на основе shapeless линз, но мне жалко компилятор - ему будет тяжело
Но с circe Encoder/Decoder он как-то справляется 🤷‍♂️
источник

ΛВ

Λнтон Войцишевский... in Scala User Group
Alex Sh
Нее... Не совсем.
Это похоже на Ad-Hoc определение линзы
john.lens(_.name).set("Mike")

Хочется, чтобы не надо было писать .lens(_.name)
Для совсем простых линз есть аннотация @Lenses, а там уже можно операторами композицию делать
источник

ΛВ

Λнтон Войцишевский... in Scala User Group
Alex Sh
Опять не то.
Тут явно указывается путь до определенного поля.
Хочется, чтобы monocle сам вывел его во время компиляции исходя из начального типа User и конечного HouseNum
Хотя я не уверен, что такое в принципе возможно.

Но всё равно хочется. Иначе очень много boilerplate code получается на определение всех нужных линз
У вас же может быть там два стринга в одном классе
источник

ΛВ

Λнтон Войцишевский... in Scala User Group
Или вы хотите уникальность типов полей в каждом классе гарантировать?
источник

AS

Alex Sh in Scala User Group
Λнтон Войцишевский
Для совсем простых линз есть аннотация @Lenses, а там уже можно операторами композицию делать
А тут у нас тоже проблема.
Мы у себя в проекте не можем использовать monocle непосредственно с классами доменной области 😔
источник

ΛВ

Λнтон Войцишевский... in Scala User Group
Alex Sh
А тут у нас тоже проблема.
Мы у себя в проекте не можем использовать monocle непосредственно с классами доменной области 😔
Мы с тем же самым столкнулись, так что обходимся генленз в отдельных объектах типа SmthLens
источник

AS

Alex Sh in Scala User Group
Λнтон Войцишевский
У вас же может быть там два стринга в одном классе
С такими кейсами понятно, что нельзя.
Я говорю только про те кейсы, когда когда конечный тип в линзе является уникальным
источник

AS

Alex Sh in Scala User Group
Λнтон Войцишевский
Мы с тем же самым столкнулись, так что обходимся генленз в отдельных объектах типа SmthLens
источник

AS

Alex Sh in Scala User Group
Можт какие-нть другие линзы такое могут?
quicklens? tofu-optics? 🤔
источник

S

Simon in Scala User Group
Alex Sh
Можт какие-нть другие линзы такое могут?
quicklens? tofu-optics? 🤔
на шейплесе можно написать поиск в глубину. Но ошибки компиляции будут так себе. И не быстро.
источник

S

Simon in Scala User Group
берешь LabeledGeneric и перебираешь все поля. Совпал тип - делаешь линзу, не совпал - ищешь линзу на тип поля рекурсивно
источник