HXT: Adding elements to a tree based on a list

111 views Asked by At

I'm struggling using arrows in the HXT library to generate elements in a tree based on a list (the line with mapM below).

mkqelem (mkQName vns "depositInstruction" pacNS) []  
    [selem "key" 
        [selem "accountId" [txt $ pacuAccountId pacUpdate],
         selem "instructionId" [txt $ pacuInstructionId pacUpdate]
        ],
     selem "totalAmount" [txt $ pacuTotalAmount pacUpdate],
     mapM mkInvestment  [(120, 10.0)]
     ]

mkInvestment :: ArrowXml a => (Fund, Amount) -> a n XmlTree
mkInvestment x = selem "investments" [selem "investmentId" [txt $ show $ fst x],selem "amount" [txt $ show $ snd x]] 

The program won't compile, I get the following:

• Couldn't match type ‘[]’ with ‘XN.NTree’
  Expected type: a n XmlTree
    Actual type: a n [XmlTree]
• In the expression: mapM mkInvestment [(120, 10.0)]
  In the third argument of ‘mkqelem’, namely
    ‘[mkelem
        "key" [] [selem "accountId" [...], selem "instructionId" [...]],
      selem "totalAmount" [txt $ pacuTotalAmount pacUpdate],
      mapM mkInvestment [(120, 10.0)]]’
  In the expression:
    mkqelem
      (mkQName vns "depositInstruction" pacNS)
      []
      [mkelem
         "key" [] [selem "accountId" [...], selem "instructionId" [...]],
       selem "totalAmount" [txt $ pacuTotalAmount pacUpdate],
       mapM mkInvestment [(120, 10.0)]]

I've tried replacing mapM with variations of +=, but I don't have a good intuition on mapping in Arrows. Any pointers?

2

There are 2 answers

1
duplode On BEST ANSWER

Your issue doesn't actually involve arrows; rather, it has to do with mapM being unnecessary here. A plain fmap over the list of tuples to make the element arrows, following by appending the result to the list with the rest of your elements, should be enough.

mkqelem (mkQName vns "depositInstruction" pacNS) [] $
    [selem "key" 
        [selem "accountId" [txt $ pacuAccountId pacUpdate],
         selem "instructionId" [txt $ pacuInstructionId pacUpdate]
        ],
     selem "totalAmount" [txt $ pacuTotalAmount pacUpdate]
     ]
    ++ fmap mkInvestment [(120, 10.0), (121, 15.0)]

As for (+=), it adds children to a node, so you wouldn't use it instead of mapM/fmap, but rather, for instance, to define mkInvestment in a different manner:

mkInvestment :: ArrowXml a => (Fund, Amount) -> a n XmlTree
mkInvestment x = eelem "investments"
    += (eelem "investmentId" += (txt $ show $ fst x))
    += (eelem "amount" += (txt $ show $ snd x))
    -- Minor style suggestion: you might prefer to use pattern matching here 
    -- instead of fst and snd.
1
bergey On

Your top code listing has a comma which is not present in the code printed by GHC in the error message. Without the comma, GHC tries to interpret mapM, mkInvestment, and [(120, 10.0)] as three arguments to selem.

I haven't tried compiling with the comma; I don't know if there are additional errors.