    {-# 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'