我有一些看起来像这样的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答案中所述.)