Обновить глубоко вложенный класс дел с помощью параметров
У меня есть трехуровневая модель класса вложенных дел с кучей опций, которые представляют некоторые данные в базе данных. Это по сути:
case class User(settings: Option[Settings])
case class Settings(keys: Option[List[KeySet]])
case class KeySet(privateKey: String, publicKey: String)
Я понимаю, как извлечь из этого глубоко вложенные поля, используя некоторые для понимания или цепочки flatMap
( Объект Option Scala внутри другого объекта Option), и я также понимаю, как обновить его с помощью библиотеки линз, но я хочу выяснить, как обновить поля, даже если некоторые элементы дерева None
и автоматически сделать Some
из тех, если они еще не существуют.
Например, как бы я справился со случаем, когда я хочу добавить к keys
Список, но пользователь еще не установил settings
? Возможно ли, в некотором смысле, автоматически создать Some(settings)
поле, а также Some(keys)
поле?
У меня есть идея, как сделать это с большим количеством сопоставления с образцом, но это кажется неправильным из-за 1. правого смещения кода и 2. не использования map
или же flatMap
очень с вариантами.
Возможно ли это, используя библиотеку линз самостоятельно? Я прочитал здесь, что это может быть невозможно: https://github.com/julien-truffaut/Monocle/issues/215 поскольку в случае с Monocle он не может обновить Option
это None
, Может быть, мне нужно подумать о проблеме по-другому?
Спасибо
1 ответ
Я не уверен, почему вы используете Option[List[KeySet]]
, Есть ли важное различие между None
и пустой List
?
В любом случае нахожу fold
быть удобным инструментом при работе с опциями.
def updateUser(u :User, ks :KeySet) :User = {
u.copy(settings =
Some(u.settings.fold(Settings(Some(ks::Nil))) (stngs =>
stngs.copy(keys = Some(stngs.keys.fold(ks::Nil) (ks::_))))))
}
val pat = updateUser(User(None), KeySet("a","b"))
//pat: User = User(Some(Settings(Some(List(KeySet(a,b))))))
val upat = updateUser(pat, KeySet("c","d"))
//upat: User = User(Some(Settings(Some(List(KeySet(c,d), KeySet(a,b))))))