Haskell 记录更新

标签 haskell record

我想用外部(流)名称/值对更新记录。记录的字段有不同的类型。

我就是这样做的,有没有更优雅的 Haskell 方法来做到这一点?

data MyRec = MyRec {field1 :: String, field2 :: Int, field3 :: Bool} deriving Show
defRec = MyRec {field1 = "", field2 = 0, field3 = False}

singleUpdate :: String -> MyRec -> MyRec  -> MyRec
singleUpdate "field1" urec rec = rec {field1 = field1 urec}
singleUpdate "field2" urec rec = rec {field2 = field2 urec}
singleUpdate "field3" urec rec = rec {field3 = field3 urec}
singleUpdate _ _ rec = rec

update :: [(String, MyRec)] -> MyRec -> MyRec
update flds rec = foldl (flip (uncurry singleUpdate)) rec flds

nameVals = [("field1",defRec {field1 = "foo"}), ("field3",defRec {field3 = True})]
updtdRec   = update nameVals defRec

updtdRec 返回 MyRec {field1 = "foo", field2 = 0, field3 = True}
有没有更紧凑的方式,更接近这样的:update field val = MyRec {field = val} (这只是伪代码),适用于所有字段,而不必为每个字段指定函数实现?

最佳答案

正如 Sibi 评论的那样,你想要的是镜头。它提供了一种操作数据类型的强大方法。

例子:

{-# LANGUAGE TemplateHaskell #-}
import Control.Lens

data MyRec = MyRec { _field1 :: String, _field2 :: Int, _field3 :: Bool } 
             deriving(Show)
makeLenses ''MyRec

main :: IO ()
main = do
  let myrec    = MyRec { _field1 = "", _field2 = 0, _field3 = False }
      myrec'   = myrec & field1 .~ "updated"
      myrec''  = myrec' & field2 .~ 1
      myrec''' = myrec'' & field3 .~ True
  print myrec    -- MyRec {_field1 = "", _field2 = 0, _field3 = False}
  print myrec'   -- MyRec {_field1 = "updated", _field2 = 0, _field3 = False}
  print myrec''  -- MyRec {_field1 = "updated", _field2 = 1, _field3 = False}
  print myrec''' -- MyRec {_field1 = "updated", _field2 = 1, _field3 = True}

你可以写一个类似 update field val = MyRec {field = val} 的函数.
update :: MyRec -> ASetter MyRec MyRec t t -> t -> MyRec
update record field val = record & field .~ val

> update defRec field1 "updated"
MyRec {_field1 = "updated", _field2 = 0, _field3 = False}

这些非常紧凑,但是镜头的元组和相应的值有不同的类型。例如,(field1, "updated")(field2, 1)有不同的类型,所以很难写一个列表来更新。

下面的链接将帮助您开始使用镜头。

https://hackage.haskell.org/package/lens-tutorial-1.0.0/docs/Control-Lens-Tutorial.html

关于Haskell 记录更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33470368/

相关文章:

alias - 在这种情况下如何为记录创建别名?

java - OrientDB 图 : How to use Java API to create a new Record?

haskell - 跟踪 haskell 列表理解?

delphi - 记录文件升级和向后兼容性

android - 使用 getSharedPreferences 保存新值

haskell - 点对美元符号

php - Foreach 循环使用 php 获取记录中数组中的最后一项?

parsing - 解析器组合器的类型

html - 如何在 EOF 处停止 Haskell Parsec 解析器

haskell - 哪些编程语言有类似 Haskell 的 `newtype`