{-# LANGUAGE MultiParamTypeClasses, FlexibleContexts, TypeFamilies,
        ScopedTypeVariables, Rank2Types #-}
-- | Type classes to allow for XML handling functions to be generalized to
-- work with different node types, including the ones defined in /Tree/ and
-- /Annotated/.
module Text.XML.Expat.Internal.NodeClass where

import Control.Monad (mzero, liftM)
import Data.Functor.Identity
import Data.List.Class (List(..), ListItem(..), cons, fromList, mapL, toList)
import Data.Monoid (Monoid)
import Text.XML.Expat.SAX (GenericXMLString)


-- | Type shortcut for attributes
type Attributes tag text = [(tag, text)]

-- | Type shortcut for attributes with unqualified names where tag and
-- text are the same string type.
type UAttributes text = Attributes text text

-- | Extract all text content from inside a tag into a single string, including
-- any text contained in children.  This /excludes/ the contents of /comments/ or
-- /processing instructions/.  To get the text for these node types, use 'getText'.
textContent :: (NodeClass n [], Monoid text) => n [] tag text -> text
textContent :: forall (n :: (* -> *) -> * -> * -> *) text tag.
(NodeClass n [], Monoid text) =>
n [] tag text -> text
textContent n [] tag text
node = Identity text -> text
forall a. Identity a -> a
runIdentity (Identity text -> text) -> Identity text -> text
forall a b. (a -> b) -> a -> b
$ n [] tag text -> ItemM [] text
forall text tag. Monoid text => n [] tag text -> ItemM [] text
forall (n :: (* -> *) -> * -> * -> *) (c :: * -> *) text tag.
(NodeClass n c, Monoid text) =>
n c tag text -> ItemM c text
textContentM n [] tag text
node

-- | A type function to give the type of a list of nodes, using the appropriate
-- list type for the specified node type, e.g. @ListOf (UNode Text)@
type family ListOf n

class (Functor c, List c) => NodeClass (n :: (* -> *) -> * -> * -> *) c where

    -- | Is the given node an element?
    isElement :: n c tag text -> Bool

    -- | Is the given node text?
    isText :: n c tag text -> Bool
    
    -- | Is the given node CData?
    isCData :: n c tag text -> Bool
    
    -- | Is the given node a processing instruction?
    isProcessingInstruction :: n c tag text -> Bool
    
    -- | Is the given node a comment?
    isComment :: n c tag text -> Bool

    -- | Extract all text content from inside a tag into a single string, including
    -- any text contained in children.  This /excludes/ the contents of /comments/ or
    -- /processing instructions/.  To get the text for these node types, use 'getText'.
    textContentM :: Monoid text => n c tag text -> ItemM c text

    -- | Is the given node a tag with the given name?
    isNamed :: Eq tag => tag -> n c tag text -> Bool

    -- | Get the name of this node if it's an element, return empty string otherwise.
    getName :: Monoid tag => n c tag text -> tag
    
    -- | Is the given node a Processing Instruction with the given target?
    hasTarget :: Eq text => text -> n c tag text -> Bool

    -- | Get the target of this node if it's a Processing Instruction, return empty string otherwise.
    getTarget :: Monoid text => n c tag text -> text

    -- | Get the attributes of a node if it's an element, return empty list otherwise.
    getAttributes :: n c tag text -> [(tag,text)]

    -- | Get children of a node if it's an element, return empty list otherwise.
    getChildren :: n c tag text -> c (n c tag text)

    -- | Get this node's text if it's a text node, comment, or processing instruction,
    -- return empty text otherwise.
    getText :: Monoid text => n c tag text -> text

    -- | Modify name if it's an element, no-op otherwise.
    modifyName :: (tag -> tag)
               -> n c tag text
               -> n c tag text

    -- | Modify attributes if it's an element, no-op otherwise.
    modifyAttributes :: ([(tag, text)] -> [(tag, text)])
                     -> n c tag text
                     -> n c tag text

    -- | Modify children (non-recursively) if it's an element, no-op otherwise.
    modifyChildren :: (c (n c tag text) -> c (n c tag text))
                   -> n c tag text
                   -> n c tag text

    -- | Map an element non-recursively, allowing the tag type to be changed.
    modifyElement :: ((tag, [(tag, text)], c (n c tag text))
                  -> (tag', [(tag', text)], c (n c tag' text)))
                  -> n c tag text
                  -> n c tag' text

    -- | Map all tags (both tag names and attribute names) recursively.
    mapAllTags :: (tag -> tag')
               -> n c tag text
               -> n c tag' text

    -- | Change a node recursively from one container type to another, with a
    -- specified function to convert the container type.
    mapNodeContainer :: List c' => 
                        (forall a . c a -> ItemM c (c' a))
                     -> n c tag text
                     -> ItemM c (n c' tag text)

    -- | Generic text node constructor.
    mkText :: text -> n c tag text

-- | Change a list of nodes recursively from one container type to another, with
-- a specified function to convert the container type.
mapNodeListContainer :: (NodeClass n c, List c') =>
                        (forall a . c a -> ItemM c (c' a))
                     -> c (n c tag text)
                     -> ItemM c (c' (n c' tag text))
mapNodeListContainer :: forall (n :: (* -> *) -> * -> * -> *) (c :: * -> *) (c' :: * -> *)
       tag text.
(NodeClass n c, List c') =>
(forall a. c a -> ItemM c (c' a))
-> c (n c tag text) -> ItemM c (c' (n c' tag text))
mapNodeListContainer forall a. c a -> ItemM c (c' a)
f = c (n c' tag text) -> ItemM c (c' (n c' tag text))
forall a. c a -> ItemM c (c' a)
f (c (n c' tag text) -> ItemM c (c' (n c' tag text)))
-> (c (n c tag text) -> c (n c' tag text))
-> c (n c tag text)
-> ItemM c (c' (n c' tag text))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (n c tag text -> ItemM c (n c' tag text))
-> c (n c tag text) -> c (n c' tag text)
forall (l :: * -> *) a b. List l => (a -> ItemM l b) -> l a -> l b
mapL ((forall a. c a -> ItemM c (c' a))
-> n c tag text -> ItemM c (n c' tag text)
forall (c' :: * -> *) tag text.
List c' =>
(forall a. c a -> ItemM c (c' a))
-> n c tag text -> ItemM c (n c' tag text)
forall (n :: (* -> *) -> * -> * -> *) (c :: * -> *) (c' :: * -> *)
       tag text.
(NodeClass n c, List c') =>
(forall a. c a -> ItemM c (c' a))
-> n c tag text -> ItemM c (n c' tag text)
mapNodeContainer c a -> ItemM c (c' a)
forall a. c a -> ItemM c (c' a)
f)

-- | Change a node recursively from one container type to another.  This
-- extracts the entire tree contents to standard lists and re-constructs them
-- with the new container type.  For monadic list types used in
-- @hexpat-iteratee@ this operation forces evaluation. 
fromNodeContainer :: (NodeClass n c, List c') => 
                     n c tag text
                  -> ItemM c (n c' tag text)
fromNodeContainer :: forall (n :: (* -> *) -> * -> * -> *) (c :: * -> *) (c' :: * -> *)
       tag text.
(NodeClass n c, List c') =>
n c tag text -> ItemM c (n c' tag text)
fromNodeContainer = (forall a. c a -> ItemM c (c' a))
-> n c tag text -> ItemM c (n c' tag text)
forall (c' :: * -> *) tag text.
List c' =>
(forall a. c a -> ItemM c (c' a))
-> n c tag text -> ItemM c (n c' tag text)
forall (n :: (* -> *) -> * -> * -> *) (c :: * -> *) (c' :: * -> *)
       tag text.
(NodeClass n c, List c') =>
(forall a. c a -> ItemM c (c' a))
-> n c tag text -> ItemM c (n c' tag text)
mapNodeContainer  (\c a
l -> [a] -> c' a
forall (l :: * -> *) a. List l => [a] -> l a
fromList ([a] -> c' a) -> ItemM c [a] -> ItemM c (c' a)
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
`liftM` c a -> ItemM c [a]
forall (l :: * -> *) a. List l => l a -> ItemM l [a]
toList c a
l)

-- | Change a list of nodes recursively from one container type to another.  This
-- extracts the entire tree contents to standard lists and re-constructs them
-- with the new container type.  For monadic list types used in
-- @hexpat-iteratee@ this operation forces evaluation.
fromNodeListContainer :: (NodeClass n c, List c') =>
                         c (n c tag text)
                      -> ItemM c (c' (n c' tag text))
fromNodeListContainer :: forall (n :: (* -> *) -> * -> * -> *) (c :: * -> *) (c' :: * -> *)
       tag text.
(NodeClass n c, List c') =>
c (n c tag text) -> ItemM c (c' (n c' tag text))
fromNodeListContainer = (forall a. c a -> ItemM c (c' a))
-> c (n c tag text) -> ItemM c (c' (n c' tag text))
forall (n :: (* -> *) -> * -> * -> *) (c :: * -> *) (c' :: * -> *)
       tag text.
(NodeClass n c, List c') =>
(forall a. c a -> ItemM c (c' a))
-> c (n c tag text) -> ItemM c (c' (n c' tag text))
mapNodeListContainer  (\c a
l -> [a] -> c' a
forall (l :: * -> *) a. List l => [a] -> l a
fromList ([a] -> c' a) -> ItemM c [a] -> ItemM c (c' a)
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
`liftM` c a -> ItemM c [a]
forall (l :: * -> *) a. List l => l a -> ItemM l [a]
toList c a
l)

-- | A class of node types where an Element can be constructed given a tag,
-- attributes and children.
class NodeClass n c => MkElementClass n c where
    -- | Generic element constructor.
    mkElement :: tag -> Attributes tag text -> c (n c tag text) -> n c tag text

-- | Get the value of the attribute having the specified name.
getAttribute :: (NodeClass n c, GenericXMLString tag) => n c tag text -> tag -> Maybe text
getAttribute :: forall (n :: (* -> *) -> * -> * -> *) (c :: * -> *) tag text.
(NodeClass n c, GenericXMLString tag) =>
n c tag text -> tag -> Maybe text
getAttribute n c tag text
n tag
t = tag -> [(tag, text)] -> Maybe text
forall a b. Eq a => a -> [(a, b)] -> Maybe b
lookup tag
t ([(tag, text)] -> Maybe text) -> [(tag, text)] -> Maybe text
forall a b. (a -> b) -> a -> b
$ n c tag text -> [(tag, text)]
forall tag text. n c tag text -> [(tag, text)]
forall (n :: (* -> *) -> * -> * -> *) (c :: * -> *) tag text.
NodeClass n c =>
n c tag text -> [(tag, text)]
getAttributes n c tag text
n

-- | Set the value of the attribute with the specified name to the value, overwriting
-- the first existing attribute with that name if present.
setAttribute :: (Eq tag, NodeClass n c, GenericXMLString tag) => tag -> text -> n c tag text -> n c tag text
setAttribute :: forall tag (n :: (* -> *) -> * -> * -> *) (c :: * -> *) text.
(Eq tag, NodeClass n c, GenericXMLString tag) =>
tag -> text -> n c tag text -> n c tag text
setAttribute tag
t text
newValue = ([(tag, text)] -> [(tag, text)]) -> n c tag text -> n c tag text
forall tag text.
([(tag, text)] -> [(tag, text)]) -> n c tag text -> n c tag text
forall (n :: (* -> *) -> * -> * -> *) (c :: * -> *) tag text.
NodeClass n c =>
([(tag, text)] -> [(tag, text)]) -> n c tag text -> n c tag text
modifyAttributes [(tag, text)] -> [(tag, text)]
set
  where
    set :: [(tag, text)] -> [(tag, text)]
set [] = [(tag
t, text
newValue)]
    set ((tag
name, text
_):[(tag, text)]
atts) | tag
name tag -> tag -> Bool
forall a. Eq a => a -> a -> Bool
== tag
t = (tag
name, text
newValue)(tag, text) -> [(tag, text)] -> [(tag, text)]
forall a. a -> [a] -> [a]
:[(tag, text)]
atts
    set ((tag, text)
att:[(tag, text)]
atts) = (tag, text)
att(tag, text) -> [(tag, text)] -> [(tag, text)]
forall a. a -> [a] -> [a]
:[(tag, text)] -> [(tag, text)]
set [(tag, text)]
atts

-- | Delete the first attribute matching the specified name.
deleteAttribute :: (Eq tag, NodeClass n c, GenericXMLString tag) => tag -> n c tag text -> n c tag text
deleteAttribute :: forall tag (n :: (* -> *) -> * -> * -> *) (c :: * -> *) text.
(Eq tag, NodeClass n c, GenericXMLString tag) =>
tag -> n c tag text -> n c tag text
deleteAttribute tag
t = ([(tag, text)] -> [(tag, text)]) -> n c tag text -> n c tag text
forall tag text.
([(tag, text)] -> [(tag, text)]) -> n c tag text -> n c tag text
forall (n :: (* -> *) -> * -> * -> *) (c :: * -> *) tag text.
NodeClass n c =>
([(tag, text)] -> [(tag, text)]) -> n c tag text -> n c tag text
modifyAttributes [(tag, text)] -> [(tag, text)]
del
  where
    del :: [(tag, text)] -> [(tag, text)]
del [] = []
    del ((tag
name, text
_):[(tag, text)]
atts) | tag
name tag -> tag -> Bool
forall a. Eq a => a -> a -> Bool
== tag
t = [(tag, text)]
atts
    del ((tag, text)
att:[(tag, text)]
atts) = (tag, text)
att(tag, text) -> [(tag, text)] -> [(tag, text)]
forall a. a -> [a] -> [a]
:[(tag, text)] -> [(tag, text)]
del [(tag, text)]
atts

-- | setAttribute if /Just/, deleteAttribute if /Nothing/.
alterAttribute :: (Eq tag, NodeClass n c, GenericXMLString tag) => tag -> Maybe text -> n c tag text -> n c tag text
alterAttribute :: forall tag (n :: (* -> *) -> * -> * -> *) (c :: * -> *) text.
(Eq tag, NodeClass n c, GenericXMLString tag) =>
tag -> Maybe text -> n c tag text -> n c tag text
alterAttribute tag
t (Just text
newValue) = tag -> text -> n c tag text -> n c tag text
forall tag (n :: (* -> *) -> * -> * -> *) (c :: * -> *) text.
(Eq tag, NodeClass n c, GenericXMLString tag) =>
tag -> text -> n c tag text -> n c tag text
setAttribute tag
t text
newValue
alterAttribute tag
t Maybe text
Nothing = tag -> n c tag text -> n c tag text
forall tag (n :: (* -> *) -> * -> * -> *) (c :: * -> *) text.
(Eq tag, NodeClass n c, GenericXMLString tag) =>
tag -> n c tag text -> n c tag text
deleteAttribute tag
t

-- | Generically convert an element of one node type to another.  Useful for
-- adding or removing annotations.
fromElement :: (NodeClass n c, MkElementClass n' c, Monoid tag, Monoid text) =>
               n c tag text
            -> n' c tag text
fromElement :: forall (n :: (* -> *) -> * -> * -> *) (c :: * -> *)
       (n' :: (* -> *) -> * -> * -> *) tag text.
(NodeClass n c, MkElementClass n' c, Monoid tag, Monoid text) =>
n c tag text -> n' c tag text
fromElement = (tag -> Attributes tag text -> c (n' c tag text) -> n' c tag text)
-> n c tag text -> n' c tag text
forall (n :: (* -> *) -> * -> * -> *) (c :: * -> *)
       (n' :: (* -> *) -> * -> * -> *) tag text.
(NodeClass n c, NodeClass n' c, Monoid tag, Monoid text) =>
(tag -> Attributes tag text -> c (n' c tag text) -> n' c tag text)
-> n c tag text -> n' c tag text
fromElement_ tag -> Attributes tag text -> c (n' c tag text) -> n' c tag text
forall tag text.
tag -> Attributes tag text -> c (n' c tag text) -> n' c tag text
forall (n :: (* -> *) -> * -> * -> *) (c :: * -> *) tag text.
MkElementClass n c =>
tag -> Attributes tag text -> c (n c tag text) -> n c tag text
mkElement

-- | Generically convert an element of one node type to another, using
-- the specified element constructor.  Useful for adding or removing annotations.
fromElement_ :: (NodeClass n c, NodeClass n' c, Monoid tag, Monoid text) =>
                (tag -> Attributes tag text -> c (n' c tag text) -> n' c tag text)  -- ^ Element constructor
             -> n c tag text
             -> n' c tag text
fromElement_ :: forall (n :: (* -> *) -> * -> * -> *) (c :: * -> *)
       (n' :: (* -> *) -> * -> * -> *) tag text.
(NodeClass n c, NodeClass n' c, Monoid tag, Monoid text) =>
(tag -> Attributes tag text -> c (n' c tag text) -> n' c tag text)
-> n c tag text -> n' c tag text
fromElement_ tag -> Attributes tag text -> c (n' c tag text) -> n' c tag text
mkElement n c tag text
elt | n c tag text -> Bool
forall tag text. n c tag text -> Bool
forall (n :: (* -> *) -> * -> * -> *) (c :: * -> *) tag text.
NodeClass n c =>
n c tag text -> Bool
isElement n c tag text
elt =
    tag -> Attributes tag text -> c (n' c tag text) -> n' c tag text
mkElement (n c tag text -> tag
forall tag text. Monoid tag => n c tag text -> tag
forall (n :: (* -> *) -> * -> * -> *) (c :: * -> *) tag text.
(NodeClass n c, Monoid tag) =>
n c tag text -> tag
getName n c tag text
elt) (n c tag text -> Attributes tag text
forall tag text. n c tag text -> [(tag, text)]
forall (n :: (* -> *) -> * -> * -> *) (c :: * -> *) tag text.
NodeClass n c =>
n c tag text -> [(tag, text)]
getAttributes n c tag text
elt) ((tag -> Attributes tag text -> c (n' c tag text) -> n' c tag text)
-> c (n c tag text) -> c (n' c tag text)
forall (n :: (* -> *) -> * -> * -> *) (c :: * -> *)
       (n' :: (* -> *) -> * -> * -> *) tag text.
(NodeClass n c, NodeClass n' c, Monoid tag, Monoid text) =>
(tag -> Attributes tag text -> c (n' c tag text) -> n' c tag text)
-> c (n c tag text) -> c (n' c tag text)
fromNodes_ tag -> Attributes tag text -> c (n' c tag text) -> n' c tag text
mkElement (c (n c tag text) -> c (n' c tag text))
-> c (n c tag text) -> c (n' c tag text)
forall a b. (a -> b) -> a -> b
$ n c tag text -> c (n c tag text)
forall tag text. n c tag text -> c (n c tag text)
forall (n :: (* -> *) -> * -> * -> *) (c :: * -> *) tag text.
NodeClass n c =>
n c tag text -> c (n c tag text)
getChildren n c tag text
elt)
fromElement_ tag -> Attributes tag text -> c (n' c tag text) -> n' c tag text
_ n c tag text
_ = [Char] -> n' c tag text
forall a. HasCallStack => [Char] -> a
error [Char]
"fromElement requires an Element"

-- | Generically convert a list of nodes from one node type to another.  Useful for
-- adding or removing annotations.
fromNodes :: (NodeClass n c, MkElementClass n' c, Monoid tag, Monoid text) =>
             c (n c tag text)
          -> c (n' c tag text)
fromNodes :: forall (n :: (* -> *) -> * -> * -> *) (c :: * -> *)
       (n' :: (* -> *) -> * -> * -> *) tag text.
(NodeClass n c, MkElementClass n' c, Monoid tag, Monoid text) =>
c (n c tag text) -> c (n' c tag text)
fromNodes = (tag -> Attributes tag text -> c (n' c tag text) -> n' c tag text)
-> c (n c tag text) -> c (n' c tag text)
forall (n :: (* -> *) -> * -> * -> *) (c :: * -> *)
       (n' :: (* -> *) -> * -> * -> *) tag text.
(NodeClass n c, NodeClass n' c, Monoid tag, Monoid text) =>
(tag -> Attributes tag text -> c (n' c tag text) -> n' c tag text)
-> c (n c tag text) -> c (n' c tag text)
fromNodes_ tag -> Attributes tag text -> c (n' c tag text) -> n' c tag text
forall tag text.
tag -> Attributes tag text -> c (n' c tag text) -> n' c tag text
forall (n :: (* -> *) -> * -> * -> *) (c :: * -> *) tag text.
MkElementClass n c =>
tag -> Attributes tag text -> c (n c tag text) -> n c tag text
mkElement

-- | Generically convert a list of nodes from one node type to another, using
-- the specified element constructor.  Useful for adding or removing annotations.
fromNodes_ :: (NodeClass n c, NodeClass n' c, Monoid tag, Monoid text) =>
              (tag -> Attributes tag text -> c (n' c tag text) -> n' c tag text)  -- ^ Element constructor
           -> c (n c tag text)
           -> c (n' c tag text)
fromNodes_ :: forall (n :: (* -> *) -> * -> * -> *) (c :: * -> *)
       (n' :: (* -> *) -> * -> * -> *) tag text.
(NodeClass n c, NodeClass n' c, Monoid tag, Monoid text) =>
(tag -> Attributes tag text -> c (n' c tag text) -> n' c tag text)
-> c (n c tag text) -> c (n' c tag text)
fromNodes_ tag -> Attributes tag text -> c (n' c tag text) -> n' c tag text
mkElement c (n c tag text)
l = ItemM c (c (n' c tag text)) -> c (n' c tag text)
forall a. ItemM c (c a) -> c a
forall (l :: * -> *) a. List l => ItemM l (l a) -> l a
joinL (ItemM c (c (n' c tag text)) -> c (n' c tag text))
-> ItemM c (c (n' c tag text)) -> c (n' c tag text)
forall a b. (a -> b) -> a -> b
$ do
    ListItem c (n c tag text)
li <- c (n c tag text) -> ItemM c (ListItem c (n c tag text))
forall a. c a -> ItemM c (ListItem c a)
forall (l :: * -> *) a. List l => l a -> ItemM l (ListItem l a)
runList c (n c tag text)
l
    c (n' c tag text) -> ItemM c (c (n' c tag text))
forall a. a -> ItemM c a
forall (m :: * -> *) a. Monad m => a -> m a
return (c (n' c tag text) -> ItemM c (c (n' c tag text)))
-> c (n' c tag text) -> ItemM c (c (n' c tag text))
forall a b. (a -> b) -> a -> b
$ case ListItem c (n c tag text)
li of
        ListItem c (n c tag text)
Nil -> c (n' c tag text)
forall a. c a
forall (m :: * -> *) a. MonadPlus m => m a
mzero
        Cons n c tag text
elt c (n c tag text)
l' | n c tag text -> Bool
forall tag text. n c tag text -> Bool
forall (n :: (* -> *) -> * -> * -> *) (c :: * -> *) tag text.
NodeClass n c =>
n c tag text -> Bool
isElement n c tag text
elt -> (tag -> Attributes tag text -> c (n' c tag text) -> n' c tag text)
-> n c tag text -> n' c tag text
forall (n :: (* -> *) -> * -> * -> *) (c :: * -> *)
       (n' :: (* -> *) -> * -> * -> *) tag text.
(NodeClass n c, NodeClass n' c, Monoid tag, Monoid text) =>
(tag -> Attributes tag text -> c (n' c tag text) -> n' c tag text)
-> n c tag text -> n' c tag text
fromElement_ tag -> Attributes tag text -> c (n' c tag text) -> n' c tag text
mkElement n c tag text
elt n' c tag text -> c (n' c tag text) -> c (n' c tag text)
forall a. a -> c a -> c a
forall (l :: * -> *) a. List l => a -> l a -> l a
`cons` (tag -> Attributes tag text -> c (n' c tag text) -> n' c tag text)
-> c (n c tag text) -> c (n' c tag text)
forall (n :: (* -> *) -> * -> * -> *) (c :: * -> *)
       (n' :: (* -> *) -> * -> * -> *) tag text.
(NodeClass n c, NodeClass n' c, Monoid tag, Monoid text) =>
(tag -> Attributes tag text -> c (n' c tag text) -> n' c tag text)
-> c (n c tag text) -> c (n' c tag text)
fromNodes_ tag -> Attributes tag text -> c (n' c tag text) -> n' c tag text
mkElement c (n c tag text)
l'
        Cons n c tag text
txt c (n c tag text)
l' | n c tag text -> Bool
forall tag text. n c tag text -> Bool
forall (n :: (* -> *) -> * -> * -> *) (c :: * -> *) tag text.
NodeClass n c =>
n c tag text -> Bool
isText n c tag text
txt    -> text -> n' c tag text
forall text tag. text -> n' c tag text
forall (n :: (* -> *) -> * -> * -> *) (c :: * -> *) text tag.
NodeClass n c =>
text -> n c tag text
mkText (n c tag text -> text
forall text tag. Monoid text => n c tag text -> text
forall (n :: (* -> *) -> * -> * -> *) (c :: * -> *) text tag.
(NodeClass n c, Monoid text) =>
n c tag text -> text
getText n c tag text
txt) n' c tag text -> c (n' c tag text) -> c (n' c tag text)
forall a. a -> c a -> c a
forall (l :: * -> *) a. List l => a -> l a -> l a
`cons` (tag -> Attributes tag text -> c (n' c tag text) -> n' c tag text)
-> c (n c tag text) -> c (n' c tag text)
forall (n :: (* -> *) -> * -> * -> *) (c :: * -> *)
       (n' :: (* -> *) -> * -> * -> *) tag text.
(NodeClass n c, NodeClass n' c, Monoid tag, Monoid text) =>
(tag -> Attributes tag text -> c (n' c tag text) -> n' c tag text)
-> c (n c tag text) -> c (n' c tag text)
fromNodes_ tag -> Attributes tag text -> c (n' c tag text) -> n' c tag text
mkElement c (n c tag text)
l'
        -- Future node types may include other kinds of nodes, which we discard here.
        Cons n c tag text
_   c (n c tag text)
l'                 -> (tag -> Attributes tag text -> c (n' c tag text) -> n' c tag text)
-> c (n c tag text) -> c (n' c tag text)
forall (n :: (* -> *) -> * -> * -> *) (c :: * -> *)
       (n' :: (* -> *) -> * -> * -> *) tag text.
(NodeClass n c, NodeClass n' c, Monoid tag, Monoid text) =>
(tag -> Attributes tag text -> c (n' c tag text) -> n' c tag text)
-> c (n c tag text) -> c (n' c tag text)
fromNodes_ tag -> Attributes tag text -> c (n' c tag text) -> n' c tag text
mkElement c (n c tag text)
l'