Haskell: стрелки на деревьях, XML и Hxt: преобразовывать текстовые листья в поддеревья - PullRequest
0 голосов
/ 22 января 2020

Фон

Приложение Freeplane , похоже, умерло за свою многолетнюю смерть. Я извлекаю из него свои данные. Freeplane сохраняет данные как XML. Один из первых шагов, которые я предпринимаю, - это гомогенизация этого формата.

Вопрос, и что я хотел сделать

Моя цель - превратить каждый элемент XText в .xml -форматированный файл в XTag, называемый "узел" с атрибутом "ТЕКСТ". Я сделал это, но таким образом, который кажется не элегантным.

Я хотел сделать это:

do 
  t <- getText
  eelem "node" >>> addAttr "TEXT" t

Но когда я попытался, мне сообщили, что монады нет для IOSLA стрелка , следовательно, do -позиция не доступна.

Возможно ли что-то подобное?

Что я сделал вместо

I копался в сыром, глубоко рекурсивном типе данных XmlTree и в итоге получил:

module Ask where

import Control.Category hiding ((.), id)
import Control.Arrow
import Text.XML.HXT.Core
import Data.Tree.NTree.TypeDefs


textToNode :: IOSArrow XmlTree XmlTree
textToNode = arr f where
  f :: XmlTree -> XmlTree
  f (NTree (XText s) children) =
    -- `children` is always an empty subtree for Text items
    let attrs = [ NTree
                  (XAttr $ mkName "TEXT")
                  [NTree (XText s) []] ]
    in NTree (XTag (mkName "node") attrs) children
  f x = x

go :: IO [XmlTree]
go =
  runX $
  readDocument [withValidate no] "flat.xml"
  >>> deepest (ifA isText textToNode none)
  >>> putXmlTree "-"

Чтобы увидеть его в действии, создайте файл с именем "flat. xml", содержащий:

<doc>
<a>1</a>
<b>2</b>
</doc>

Когда вы запустите go, вы получите обратно «1» и «2», но вставлены в XTag s следующим образом:

---XTag "node"
   |   "TEXT"="1"

(Вам также вернутся пробелы; это не важно.)

1 Ответ

1 голос
/ 23 января 2020

Arrow не имеет обозначения do, но имеет нечто похожее, называемое proc обозначением или синтаксисом стрелки. В частности, см. этот вопрос об отношении между этими двумя обозначениями. При этом вы можете написать в стиле, аналогичном тому, что вы хотели сделать:

textToNode :: IOSArrow XmlTree XmlTree
textToNode = proc x -> do
  text <- getText -< x
  node <- eelem "node" -<< text
  tree <- addAttr "TEXT" text -<< node
  returnA -< tree

Здесь <- аналогично его monadi c аналогу, а -<< val действует как -< returnA val и позволяет связывать стрелки. Обратите внимание, что вам нужно будет включить расширение языка GH C:

{-# LANGUAGE Arrows #-}
...