Обновить глубоко вложенный класс дел с помощью параметров

У меня есть трехуровневая модель класса вложенных дел с кучей опций, которые представляют некоторые данные в базе данных. Это по сути:

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))))))
Другие вопросы по тегам