
The XML toolboxes HaXml, HXML and the XML toolbox uses one function type (called filter) for different purposes. The functions of types predicates a -> Bool selectors, transformators a -> a list-valued functions a -> [a] are all implemented with the one type (a -> [a]). In this design predicates don't return False or True, but an empty list or a one-element list containing the input value. Transformators return single element lists. In my opinion this means a significant loss of type safety and quality of documentation. Are there more type safe XML/HTML processor libraries in Haskell?

Henning Thielemann
The XML toolboxes HaXml, HXML and the XML toolbox uses one function type (called filter) for different purposes.
predicates a -> Bool selectors, transformators a -> a list-valued functions a -> [a]
are all implemented with the one type (a -> [a]).
In my opinion this means a significant loss of type safety and quality of documentation. Are there more type safe XML/HTML processor libraries in Haskell?
When we were first experimenting with designs that later became HaXml, we did indeed have separate notions of predicate, transformer, selector, and so on. But having lots of different types like this meant it was more difficult to plug things together nicely into a combinator framework. Thus, we decided to squash everything together into the filter type, so each piece was modular and could fit with any other piece. I think it was a good design. But I take your point that this approach reduces type safety. One option we considered was to use the DTD "type" of XML document fragments themselves as a basis for a type system over the combinator library. Doubtless this would have required some subtle class machinery to overload the same operation over many different DTDs. Maybe even dependent types, subtyping, or union/intersection types would be needed to get it just right. In the end, we decided that the mismatch between DTDs and Hindley-Milner was too great to do a good job here, so the combinator library remained rather generic and almost typeless. Regards, Malcolm

On Tue, 12 Apr 2005, Malcolm Wallace wrote:
Henning Thielemann
writes: The XML toolboxes HaXml, HXML and the XML toolbox uses one function type (called filter) for different purposes.
predicates a -> Bool selectors, transformators a -> a list-valued functions a -> [a]
are all implemented with the one type (a -> [a]).
In my opinion this means a significant loss of type safety and quality of documentation. Are there more type safe XML/HTML processor libraries in Haskell?
When we were first experimenting with designs that later became HaXml, we did indeed have separate notions of predicate, transformer, selector, and so on. But having lots of different types like this meant it was more difficult to plug things together nicely into a combinator framework. Thus, we decided to squash everything together into the filter type, so each piece was modular and could fit with any other piece. I think it was a good design.
What about providing combinators for the most common cases and provide lifting functions for the uncommon cases, such as liftPred :: (a -> Bool) -> (a -> [a]) liftPred p x = if p x then [x] else [] liftTrans :: (a -> b) -> (a -> [b]) liftTrans f x = [f x] ?

Henning Thielemann
predicates a -> Bool selectors, transformators a -> a list-valued functions a -> [a]
What about providing combinators for the most common cases and provide lifting functions for the uncommon cases, such as
liftPred :: (a -> Bool) -> (a -> [a]) liftPred p x = if p x then [x] else []
liftTrans :: (a -> b) -> (a -> [b]) liftTrans f x = [f x]
Looks good. If you want to come up with a concrete design for an fuller set of alternative combinators, I'd be happy to include it into HaXml as a further choice of facility. Regards, Malcolm

At 13:48 12/04/05 +0100, Malcolm Wallace wrote:
Henning Thielemann
writes: predicates a -> Bool selectors, transformators a -> a list-valued functions a -> [a]
What about providing combinators for the most common cases and provide lifting functions for the uncommon cases, such as
liftPred :: (a -> Bool) -> (a -> [a]) liftPred p x = if p x then [x] else []
liftTrans :: (a -> b) -> (a -> [b]) liftTrans f x = [f x]
Looks good. If you want to come up with a concrete design for an fuller set of alternative combinators, I'd be happy to include it into HaXml as a further choice of facility.
Obliquely related to this thread: When I added namespace support and other stuff to HaXml, I added (a) and "infoset" type parameter to the XML document type [1], and (b) a new transformation type [2] so that I could create new document types with additional information in the Haskell data to support features like XML namesspaces and xml:base. I think your proposals could also be added into this framework, with the additional wrinkle that using a 'newtype' in the "infoset" value type, one could maybe achieve a degree of type safety, but at the cost of losing some of the algebraic properties of a 'CFilter'. My version is on my web site (sorry I'm offline and can't find the actual URI right now). #g -- [1] From my version of Text.XML.HaXml.Types: [[ data DocumentI i = Document Prolog (SymTab EntityDef) (ElementI i) data ElementI i = Elem QName i [Attribute] [ContentI i] data ElemTag = ElemTag Name [Attribute] -- ^ intermediate for parsing type Attribute = (QName, AttValue) data ContentI i = CElem (ElementI i) | CString Bool CharData -- Bool flags whitespace significance | CRef Reference | CMisc Misc | CErr String -- Fudge to get error diagnostics -- from a filter data ElementInfoset = EI { eiNamespaces :: [Namespace] , eiBase :: String -- Non-infoset values -- (in xml namespace: http://www.w3.org/XML/1998/namespace) , eiLang :: String , eiSpace :: Bool -- True=preserve, False=default -- ? , eiIdent :: String -- xml:id, or other ID value? } deriving Show ]] So that: [[ type Document = DocumentI () type Element = ElementI () type Content = ContentI () ]] Provide compatibility with existing HaXml, but I can use [[ DocumentI ElementInfoset ElementI ElementInfoset ContentI ElementInfoset ]] ... [2] From my version of Text.XML.HaXml.Combinators: [[ type CTransform i1 i2 = ContentI i1 -> [ContentI i2] type CFilterI i = CTransform i i type CFilter = CFilterI () ]] ------------ Graham Klyne For email: http://www.ninebynine.org/#Contact
participants (3)
-
Graham Klyne
-
Henning Thielemann
-
Malcolm Wallace