List 更新记录集合中记录中的单个值Haskell

List 更新记录集合中记录中的单个值Haskell,list,haskell,insert,record,List,Haskell,Insert,Record,所以我有一个自定义的数据类型Person 我有一个这样的列表,foo=[Person] 我正在尝试更新一个特定的人。我的过程是匹配它们的fname,假设每个名称都是唯一的,然后更新它们的同胞值 我真的很难“从功能上”思考,如果我用命令式语言来做这件事,我可以在[Person]中检查每一项,看看name==fname,然后是this.wills推新闻发布或类似的东西 我知道如何更新haskell中的记录,但我想在更新Person集合中的单个Person后返回Person列表 我就是不知道如何“思考

所以我有一个自定义的数据类型Person

我有一个这样的列表,foo=[Person]

我正在尝试更新一个特定的人。我的过程是匹配它们的fname,假设每个名称都是唯一的,然后更新它们的同胞值

我真的很难“从功能上”思考,如果我用命令式语言来做这件事,我可以在[Person]中检查每一项,看看name==fname,然后是this.wills推新闻发布或类似的东西

我知道如何更新haskell中的记录,但我想在更新Person集合中的单个Person后返回Person列表

我就是不知道如何“思考Haskell”


谢谢:

您不应该考虑更新某些内容,即使我们使用该术语,除非您有一个可变引用并且正在使用IO monad。在这种情况下,思考的过程应该是如何计算一个与前一个列表完全相同的新列表,除了

您可以更新单个条目,也可以在整个列表中映射修改函数。让我们先看一下手册、单条目解决方案:

addSiblingToPerson :: String -> String -> [Person] -> [Person]
addSiblingToPerson siblingParam fnameParam allPeople = 
    case allPeople of
       []     -> []
       (p:ps) | fname p == fnameParam ->
                     p { siblings = siblingParam : siblings p } : ps
              | otherwise ->
                     p : addSiblingToPerson siblingParam fnameParam ps
也就是说,我们遍历列表,保留所有不匹配的人,并用匹配的fname更新第一个人,确保包括列表的其余部分

地图解决方案在功能上是不同的——它将更新共享给定fname的所有人,并遍历整个列表

addSiblingToPerson :: String -> String -> [Person] -> [Person]
addSiblingToPerson siblingParam fnameParam allPeople =
      let update p | fname p == fnameParam = p { siblings = siblingParam : siblings p }
                   | otherwise = p
      in map update allPeople

探索令人兴奋的世界。谢谢。如何计算一个与前一个列表完全相同的新列表,除了。。。。真的帮助我明白了。当然,仅仅为了修改一个值而创建一个完整的新列表是低效的?不是说你的答案不令人满意,这很好,真的帮助我理解了,但更多的是指向哈斯克尔。首先:你是对的。当然,在这种情况下,如果您希望获得良好的性能,列表不是您想要使用的结构。第二:不要过早地对你认为有效的东西挂断电话。在本例中,第一次匹配后的列表部分将被共享-更新前和更新后的列表都有指向公共尾部的指针。在Haskell中,大多数值都是装箱的,许多更新操作涉及的是将指针移动到旧结构、旧元素等。请注意,即使可以在适当的位置对列表进行修改,这也是低效的。要找到需要更新的元素,您需要做一些额外的工作,因此复制不匹配的元素并不是什么大问题。
addSiblingToPerson :: String -> String -> [Person] -> [Person]
addSiblingToPerson siblingParam fnameParam allPeople = 
    case allPeople of
       []     -> []
       (p:ps) | fname p == fnameParam ->
                     p { siblings = siblingParam : siblings p } : ps
              | otherwise ->
                     p : addSiblingToPerson siblingParam fnameParam ps
addSiblingToPerson :: String -> String -> [Person] -> [Person]
addSiblingToPerson siblingParam fnameParam allPeople =
      let update p | fname p == fnameParam = p { siblings = siblingParam : siblings p }
                   | otherwise = p
      in map update allPeople