Pregunta

Estoy tratando de llegar a un acuerdo con Caja de herramientas XML de Haskell ( HXT ) y yo' m golpear una pared en alguna parte, porque no parecen comprender plenamente las flechas como una herramienta computacional.

Aquí está mi problema, que yo esperaba para ilustrar un poco mejor utilizando una sesión 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]

Así Parse es una pequeña función auxiliar que se aplica cualquiera que sea Flecha le doy al documento XML trivial

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

I definir otra función auxiliar, esta vez para extraer el texto por debajo de un nodo con un nombre dado:

> 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")]

Con la ayuda de esta función, es fácil utilizar el combinador &&& a emparejar el texto de dos nodos diferentes, y luego, por ejemplo, pasarlo a un constructor, como esto:

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

Ahora viene la parte que no entiendo: Quiero-factor de la izquierda! llamadas extract getChildren en el nodo raíz dos veces. En su lugar, me gustaría sólo para llamar una vez! Así que primero sale el hijo del nodo raíz

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

Tenga en cuenta, que he tratado de reordenar las llamadas a, digamos, isElem, etc con el fin de averiguar si esa es la cuestión. Pero tal como está, sólo que no tengo idea de por qué esto no está funcionando. Hay una flecha 'tutorial' en el Haskell wiki y la forma en que lo entendía, se debe sea posible hacer lo que quiero hacer de esa manera -. a saber utilizar &&& con el fin de emparejar los resultados de dos cálculos

No funciona, también - pero sólo al comienzo de la flecha de la cadena, a través no a mitad de camino, cuando tengo algunos resultados ya, que yo quiero seguir 'compartida'. Tengo la sensación de que simplemente no estoy siendo capaz de envolver mi cabeza en torno a una diferencia en la composición de ideas entre la función normal y la flecha notación. Estaría muy agradecido por cualquier punteros! (Incluso si es sólo a algunos genérica flecha-tutorial que va un poco más profundo que el de la Haskell-wiki.)

Gracias!

¿Fue útil?

Solución

Si convierte la flecha a (y desde) una versión determinista esta funciona como se espera:

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

Esto no es realmente satisfactoria, sin embargo, y no puedo recordar la parte superior de mi cabeza por qué (&&&) comporta de esta manera con una flecha no determinista (yo personalmente uso el proc/do notación para cualquier cosa mucho más complicado que esto).


ACTUALIZACIÓN: Parece que hay algo raro pasa aquí con runLA y xread. Si utiliza runX y readString todo funciona como se espera:

> 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")]

Esto significa que tiene que ejecutar el programa de análisis de la mónada IO, pero hay ventajas en el uso de todos modos runX (mensajes de error mejor, etc.).

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top