Haskell动态数据类型的更改

时间:2011-12-14 17:36:48

标签: haskell

我有一些看起来像这样的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中做这样的事情?

2 个答案:

答案 0 :(得分:13)

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

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

另一种流行的镜头包是fclabels。我更喜欢数据镜头的简单性和速度; fclabels(从版​​本1.0开始)稍微灵活一些,但是你不需要那么灵活。 (请注意,由于其新增的灵活性,fclabels'State类型无法直接转换为镜头的简单定义,如我链接的Stack Overflow答案中所述。)

答案 1 :(得分:1)

如果没有Template Haskell,这是不可能的。您可以使用data-accessor和data-accessor-template来删除此类锅炉板。