【问题标题】:Haskell dynamic data-type alterationHaskell 动态数据类型更改
【发布时间】:2012-01-20 11:56:23
【问题描述】:

我有一些类似这样的 Haskell 样板:

data Configuration
    { confA :: Integer
    , confB :: Boolean
    , confC :: String }

x = (\arg opt -> opt{ confA=arg })
y = (\arg opt -> opt{ confB=arg })
z = (\arg opt -> opt{ confC=arg })

我想删除样板,产生如下内容:

setter :: (Config -> a) -> a -> Config -> Config
x = setter confA
y = setter confB
z = setter confC

但我不知道如何构造这样的setter 函数。这甚至可能在(非模板)haskell 中还是我在这里与语法糖对接?如果是这样,我将如何在模板 haskell 中做这样的事情?

【问题讨论】:

    标签: haskell


    【解决方案1】:

    仅使用 Haskell 的记录系统是不可能的。你想要的是镜头;这个previous Stack Overflow question 及其最佳答案是一个很好的介绍。就个人而言,我使用那里提到的data-lens 包。 (另请参阅 data-lens-fd 将它与 mtl 的 MonadState 类一起使用 - 如果你不知道那是什么,只要知道你可能应该在你想在 State monad 中使用镜头时使用它。)

    data-lens-template 包可能是你想要的 Template Haskell 应用程序;它为记录场导出镜头定义。

    另一个流行的镜头包是fclabels。我更喜欢 data-lens 的简单性和速度; fclabels(从 1.0 版开始)稍微灵活一些,但你不需要那种灵活性来做你想做的事。 (请注意,由于其新增加的灵活性,fclabels 的(:->) 类型不能再直接转换为镜头的简单定义,如我链接的 Stack Overflow 答案中所述。)

    【讨论】:

      【解决方案2】:

      没有模板 Haskell,这是不可能的。您可以使用 data-accessor 和 data-accessor-template 来删除此类样板。

      【讨论】:

      • 我相信这是正确的。记录语法会自动为您创建 getter,但是当您想要创建 setter 时,这些大多是无用的。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-01-02
      • 1970-01-01
      • 1970-01-01
      • 2016-11-09
      • 1970-01-01
      • 2020-03-05
      • 2021-06-16
      相关资源
      最近更新 更多