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

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

case class User(settings: Option[Settings])
case class Settings(keys: Option[List[KeySet]])
case class KeySet(privateKey: String, publicKey: String)

Я понимаю, как получить из этого глубоко вложенные поля, используя некоторые для понимания или цепочки flatMap (объект Scala Option внутри другого объекта Option), и я также понимаю, как обновлять его с помощью библиотеки объективов, но я хочу выяснить, как обновлять поля, даже если некоторые элементы в дереве None и автоматически Some из них, если они еще не существуют.

Например, как мне поступить в случае, когда я хочу добавить в список keys, но пользователь еще не установил ни одного settings? Можно ли в каком-то смысле автоматически создать поле Some(settings), а также поле Some(keys)?

У меня есть идея, как это сделать с большим количеством сопоставлений с образцом, но это кажется неправильным из-за 1. смещения кода вправо и 2. нечастого использования map или flatMap с параметрами.

Возможно ли это с помощью отдельной библиотеки объективов? Я прочитал здесь, что это может быть невозможно: https://github.com/julien-truffaut/Monocle/issues/215, как и в случае с Monocle, он не может обновить Option, который является None. Может быть, мне нужно подумать о проблеме с другой стороны?

Спасибо


person coolboyjules    schedule 11.04.2018    source источник


Ответы (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))))))
person jwvh    schedule 11.04.2018