Question

Je suis en train de venir à bout avec boîte à outils XML Haskell ( HXT ) et I » m frapper un endroit de mur, parce que je ne semble pas bien saisir les flèches comme un outil de calcul.

Voici mon problème, que j'espérais illustrer un peu mieux à l'aide d'une session GHCi:

> let parse p = runLA (xread >>> p) "<root><a>foo</a><b>bar</b><c>baz</c></root>"
> :t parse
parse :: LA XmlTree b -> [b]

Parse est une petite fonction d'aide qui applique ce qu'il ARROW je donne au document XML trivial

<root>
  <a>foo</a>
  <b>bar</b>
  <c>baz</c>
</root>

Je définir une autre fonction d'aide, cette fois-ci pour extraire le texte ci-dessous un nœud avec un nom donné:

> let extract s = getChildren >>> isElem >>> hasName s >>> getChildren >>> getText 
> :t extract
extract :: (ArrowXml cat) =>
   String -> cat (Data.Tree.NTree.TypeDefs.NTree XNode) String
> parse (extract "a" &&& extract "b") -- extract two nodes' content.
[("foo","bar")]

Avec l'aide de cette fonction, il est facile d'utiliser le combinateur &&& pour jumeler le texte de deux nœuds différents, puis, par exemple, passer à un constructeur, comme ceci:

> parse (extract "a" &&& extract "b" >>^ arr (\(a,b) -> (b,a))) 
[("bar","foo")]

Maintenant vient la partie que je ne comprends pas: je veux facteur gauche! appels extract getChildren sur le nœud racine deux fois. Au lieu de cela, je voudrais que ce ne l'appeler une fois! Donc, j'obtiens d'abord l'enfant du nœud racine

> let extract' s = hasName s >>> getChildren >>> getText
> :t extract'
extract' :: (ArrowXml cat) => String -> cat XmlTree String
> parse (getChildren >>> isElem >>> (extract' "a" &&& extract' "b"))
[]

Notez que j'ai essayé de réordonner les appels à, disons, isElem, etc., afin de savoir si c'est la question. Mais tel qu'il est, je n'ai aucune idée pourquoi cela ne fonctionne pas. Il y a une flèche « tutoriel » sur le wiki Haskell et la façon dont je l'ai compris, il devrait est possible de faire ce que je veux faire de cette façon -. utiliser à savoir &&& afin de jumeler les résultats de deux calculs

Il fonctionne aussi - mais seulement au début de la chaîne flèche, pas à mi-chemin creux, quand j'ai quelques résultats déjà, que je veux garder « partagé ». J'ai le sentiment que je ne suis pas pouvoir envelopper ma tête autour d'une différence d'idées entre la composition de la fonction normale et flèche notation. Je serais très reconnaissant de tous les pointeurs! (Même si elle est juste une flèche tutoriel générique qui va un peu plus en profondeur que le Haskell sur le wiki.)

Merci!

Était-ce utile?

La solution

Si vous convertissez la flèche (puis de) une version déterministe cela fonctionne comme prévu:

> let extract' s = unlistA >>> hasName s >>> getChildren >>> getText
> parse (listA (getChildren >>> isElem) >>> (extract' "a" &&& extract' "b"))
[("foo","bar")]

Ce n'est pas vraiment satisfaisante, bien que, et je ne me souviens pas du haut de ma tête pourquoi (&&&) se comporte de cette façon avec une flèche non déterministes (personnellement je l'utilise proc/do notation pour quoi que ce soit beaucoup plus compliqué que cela).


Mise à jour: Il semble y avoir quelque chose de bizarre se passe ici avec runLA et xread. Si vous utilisez tout runX et readString fonctionne comme prévu:

> let xml = "<root><a>foo</a><b>bar</b><c>baz</c></root>"
> let parse p = runX (readString [] xml >>> p)
> let extract' s = getChildren >>> hasName s >>> getChildren >>> getText
> parse (getChildren >>> isElem >>> (extract' "a" &&& extract' "b"))
[("foo","bar")]

Cela signifie que vous devez exécuter l'analyseur dans la monade IO, mais il y a des avantages à utiliser runX (de toute façon mieux les messages d'erreur, etc.).

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top