【问题标题】:Update deeply nested case class with Options使用选项更新深度嵌套的案例类
【发布时间】:2018-09-21 12:54:58
【问题描述】:

我有一个 3 级嵌套案例类模型,其中包含一组代表数据库中一些数据的选项。本质上是:

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

我了解如何使用一些用于理解或flatMap (Scala Option object inside another Option object) 的链来从中获得深度嵌套的字段,并且我也了解如何使用镜头库对其进行更新,但我想弄清楚如何即使树中的某些内容是 None 也要更新字段,如果这些内容尚不存在,则自动生成 Somes。

例如,如果我想添加到keys 列表但用户尚未设置任何settings,我将如何处理?是否可以在某种意义上自动创建Some(settings) 字段和Some(keys) 字段?

我知道如何通过大量模式匹配来做到这一点,但这似乎是错误的,因为 1. 代码向右漂移和 2. 没有使用 mapflatMap 非常多的选项。

这可以单独使用镜头库吗?我在这里读到这可能是不可能的:https://github.com/julien-truffaut/Monocle/issues/215 就像 Monocle 的情况一样,它无法更新OptionNone。或许我需要换个方式思考这个问题?

谢谢

【问题讨论】:

    标签: scala lenses monocle-scala


    【解决方案1】:

    我不确定你为什么使用Option[List[KeySet]]None 和空的 List 之间是否有重要区别?

    无论如何,我发现fold 在使用 Options 时是一个方便的工具。

    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))))))
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-12
      • 2018-06-04
      • 2018-11-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多