Concise way of “updating” element in nested collections





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ margin-bottom:0;
}







0












$begingroup$


Imagine simple game:



type Combatant = {
hp : int
attack : int
}

type CombatantGroup = Combatant list
type CombatantGroups = CombatantGroup list

type Battle = {
combatantGroups : CombatantGroups
}



there is some battle, in which some amount groups participate. In each group there is several combatants. Now I want to implement a function for one combatant to attack another. Due to immutability, I have to replace whole attacked target, and whole group and whole battle. If the battle was just between two participants, I could write code like this:



if target = battle.combatant1 then
{ battle with combatant1 = { battle.combatant1 with hp = battle.combatant1.hp - attacker.attack }}
else
{ battle with combatant2 = { battle.combatant2 with hp = battle.combatant2.hp - attacker.attack }}


which is also terrible code, I would appreciate any advice on it. But with nested collections it gets even more complicated, and event doesn't look functional to me anymore:



let containsTarget = List.contains target        
let transformCombatant combatant = if combatant = target then { combatant with hp = combatant.hp - attacker.attack } else combatant
let transformGroup = List.map transformCombatant
let checkGroup group =
if group |> containsTarget then
group |> transformGroup
else
group
let transformGroups = List.map checkGroup

{ battle with combatantGroups = transformGroups battle.combatantGroups }


Can you please give me advise on how can I use features of F# and functional programming, to make given code more pretty and concise?









share







New contributor




Dmitry Pavlushin is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.







$endgroup$



















    0












    $begingroup$


    Imagine simple game:



    type Combatant = {
    hp : int
    attack : int
    }

    type CombatantGroup = Combatant list
    type CombatantGroups = CombatantGroup list

    type Battle = {
    combatantGroups : CombatantGroups
    }



    there is some battle, in which some amount groups participate. In each group there is several combatants. Now I want to implement a function for one combatant to attack another. Due to immutability, I have to replace whole attacked target, and whole group and whole battle. If the battle was just between two participants, I could write code like this:



    if target = battle.combatant1 then
    { battle with combatant1 = { battle.combatant1 with hp = battle.combatant1.hp - attacker.attack }}
    else
    { battle with combatant2 = { battle.combatant2 with hp = battle.combatant2.hp - attacker.attack }}


    which is also terrible code, I would appreciate any advice on it. But with nested collections it gets even more complicated, and event doesn't look functional to me anymore:



    let containsTarget = List.contains target        
    let transformCombatant combatant = if combatant = target then { combatant with hp = combatant.hp - attacker.attack } else combatant
    let transformGroup = List.map transformCombatant
    let checkGroup group =
    if group |> containsTarget then
    group |> transformGroup
    else
    group
    let transformGroups = List.map checkGroup

    { battle with combatantGroups = transformGroups battle.combatantGroups }


    Can you please give me advise on how can I use features of F# and functional programming, to make given code more pretty and concise?









    share







    New contributor




    Dmitry Pavlushin is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
    Check out our Code of Conduct.







    $endgroup$















      0












      0








      0





      $begingroup$


      Imagine simple game:



      type Combatant = {
      hp : int
      attack : int
      }

      type CombatantGroup = Combatant list
      type CombatantGroups = CombatantGroup list

      type Battle = {
      combatantGroups : CombatantGroups
      }



      there is some battle, in which some amount groups participate. In each group there is several combatants. Now I want to implement a function for one combatant to attack another. Due to immutability, I have to replace whole attacked target, and whole group and whole battle. If the battle was just between two participants, I could write code like this:



      if target = battle.combatant1 then
      { battle with combatant1 = { battle.combatant1 with hp = battle.combatant1.hp - attacker.attack }}
      else
      { battle with combatant2 = { battle.combatant2 with hp = battle.combatant2.hp - attacker.attack }}


      which is also terrible code, I would appreciate any advice on it. But with nested collections it gets even more complicated, and event doesn't look functional to me anymore:



      let containsTarget = List.contains target        
      let transformCombatant combatant = if combatant = target then { combatant with hp = combatant.hp - attacker.attack } else combatant
      let transformGroup = List.map transformCombatant
      let checkGroup group =
      if group |> containsTarget then
      group |> transformGroup
      else
      group
      let transformGroups = List.map checkGroup

      { battle with combatantGroups = transformGroups battle.combatantGroups }


      Can you please give me advise on how can I use features of F# and functional programming, to make given code more pretty and concise?









      share







      New contributor




      Dmitry Pavlushin is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.







      $endgroup$




      Imagine simple game:



      type Combatant = {
      hp : int
      attack : int
      }

      type CombatantGroup = Combatant list
      type CombatantGroups = CombatantGroup list

      type Battle = {
      combatantGroups : CombatantGroups
      }



      there is some battle, in which some amount groups participate. In each group there is several combatants. Now I want to implement a function for one combatant to attack another. Due to immutability, I have to replace whole attacked target, and whole group and whole battle. If the battle was just between two participants, I could write code like this:



      if target = battle.combatant1 then
      { battle with combatant1 = { battle.combatant1 with hp = battle.combatant1.hp - attacker.attack }}
      else
      { battle with combatant2 = { battle.combatant2 with hp = battle.combatant2.hp - attacker.attack }}


      which is also terrible code, I would appreciate any advice on it. But with nested collections it gets even more complicated, and event doesn't look functional to me anymore:



      let containsTarget = List.contains target        
      let transformCombatant combatant = if combatant = target then { combatant with hp = combatant.hp - attacker.attack } else combatant
      let transformGroup = List.map transformCombatant
      let checkGroup group =
      if group |> containsTarget then
      group |> transformGroup
      else
      group
      let transformGroups = List.map checkGroup

      { battle with combatantGroups = transformGroups battle.combatantGroups }


      Can you please give me advise on how can I use features of F# and functional programming, to make given code more pretty and concise?







      .net functional-programming f#





      share







      New contributor




      Dmitry Pavlushin is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.










      share







      New contributor




      Dmitry Pavlushin is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.








      share



      share






      New contributor




      Dmitry Pavlushin is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.









      asked 4 mins ago









      Dmitry PavlushinDmitry Pavlushin

      1011




      1011




      New contributor




      Dmitry Pavlushin is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.





      New contributor





      Dmitry Pavlushin is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.






      Dmitry Pavlushin is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.






















          0






          active

          oldest

          votes












          Your Answer





          StackExchange.ifUsing("editor", function () {
          return StackExchange.using("mathjaxEditing", function () {
          StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
          StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
          });
          });
          }, "mathjax-editing");

          StackExchange.ifUsing("editor", function () {
          StackExchange.using("externalEditor", function () {
          StackExchange.using("snippets", function () {
          StackExchange.snippets.init();
          });
          });
          }, "code-snippets");

          StackExchange.ready(function() {
          var channelOptions = {
          tags: "".split(" "),
          id: "196"
          };
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function() {
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled) {
          StackExchange.using("snippets", function() {
          createEditor();
          });
          }
          else {
          createEditor();
          }
          });

          function createEditor() {
          StackExchange.prepareEditor({
          heartbeatType: 'answer',
          autoActivateHeartbeat: false,
          convertImagesToLinks: false,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: null,
          bindNavPrevention: true,
          postfix: "",
          imageUploader: {
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          },
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          });


          }
          });






          Dmitry Pavlushin is a new contributor. Be nice, and check out our Code of Conduct.










          draft saved

          draft discarded


















          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f216909%2fconcise-way-of-updating-element-in-nested-collections%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown

























          0






          active

          oldest

          votes








          0






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes








          Dmitry Pavlushin is a new contributor. Be nice, and check out our Code of Conduct.










          draft saved

          draft discarded


















          Dmitry Pavlushin is a new contributor. Be nice, and check out our Code of Conduct.













          Dmitry Pavlushin is a new contributor. Be nice, and check out our Code of Conduct.












          Dmitry Pavlushin is a new contributor. Be nice, and check out our Code of Conduct.
















          Thanks for contributing an answer to Code Review Stack Exchange!


          • Please be sure to answer the question. Provide details and share your research!

          But avoid



          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.


          Use MathJax to format equations. MathJax reference.


          To learn more, see our tips on writing great answers.




          draft saved


          draft discarded














          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f216909%2fconcise-way-of-updating-element-in-nested-collections%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown





















































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown

































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown







          Popular posts from this blog

          Список кардиналов, возведённых папой римским Каликстом III

          Deduzione

          Mysql.sock missing - “Can't connect to local MySQL server through socket”