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

时间:2017-03-16 13:55:50

标签: list haskell insert record

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

   data Person = Person{ fname :: String
                        , lname :: String
                        , age :: Int
                        , siblings :: [String]
                        }

我有一个这种类型的列表,foo = [Person].

我正在尝试更新特定的Person。我的流程是匹配他们的fname(假设每个名称都是唯一的),然后更新他们的siblings值。

addSiblingToPerson :: String -> String -> [Person] -> [Person]
addSiblingToPerson siblingParam fnameParam fooParam = 

我真的在努力思考“功能性”,如果我用命令式语言这样做,我可以通过[Person]检查if name == fname then this.siblings push newSibling中的每个项目来查看Person(或者沿着这些行)

我知道如何更新haskell中的记录,但我希望在更新Person集合中的单个人后返回public class GetLocationDownloadTask extends AsyncTask<String, Void, String> { @Override protected String doInBackground(String... strings) { String result = ""; URL url; HttpURLConnection urlConnection; try { url = new URL(strings[0]); urlConnection = (HttpURLConnection) url.openConnection(); InputStream is = urlConnection.getInputStream(); InputStreamReader inputStreamReader = new InputStreamReader(is); int data = inputStreamReader.read(); while(data != -1){ char curr = (char) data; result += curr; data = inputStreamReader.read(); } return result; } catch (Exception e) { e.printStackTrace(); } return null; } @Override protected void onPostExecute(String result) { super.onPostExecute(result); if(result != null) { try { JSONObject locationObject = new JSONObject(result); JSONObject locationGeo = locationObject.getJSONArray("results").getJSONObject(0).getJSONObject("geometry").getJSONObject("location"); } catch (JSONException e) { e.printStackTrace(); } } } 列表。

我无法理解如何“思考Haskell”

谢谢:(

1 个答案:

答案 0 :(得分:1)

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

您可以在整个列表中更新单个条目或map修改功能。让我们先看一下手册,单项,解决方案:

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