Haskell动态数据类型的更改

So8*_*res 6 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 })
Run Code Online (Sandbox Code Playgroud)

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

setter :: (Config -> a) -> a -> Config -> Config
x = setter confA
y = setter confB
z = setter confC
Run Code Online (Sandbox Code Playgroud)

但我不知道如何构建这样的setter功能.这甚至可能在(非模板)haskell中,还是我在这里对抗语法糖?如果是这样,我将如何在模板haskell中做这样的事情?

ehi*_*ird 13

只有Haskell的记录系统才能实现这一点.你想要的是镜头 ; 这个以前的Stack Overflow问题及其最佳答案是一个很好的介绍.就个人而言,我使用的是数据镜头包.(另请参阅data-lens-fd将它与mtl 的MonadState类一起使用- 如果你不知道那是什么,只要知道你应该在你想在Statemonad中使用镜头时使用它.)

数据镜头模板包可能是你想要的模板哈斯克尔的应用; 它导出记录字段的镜头定义.

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