
I've been playing with HaXmL lately. I've had a need to convert one XML document to another, and HaXmL was very nice for that. Along the way, I've discovered that I need to do some I/O as part of the conversion (specifically due to timezone-related calculations). Much of HaXML is based around the CFilter type: type CFilter = Content -> [Content] That is, most of the stuff one does in HaXML is a function with that type. Try as I might, I could not figure out a nice way to integrate I/O into this system. A simple IO CFilter wouldn't work, since there has to be input available when it runs. Content -> IO [Content] didn't work either, since the IO ripples up all the way to the top, messing up the nice code everywhere. I finally resorted to unsafePerformIO to get it done. But I'd like to know the proper solution. I do hope that this is not it :-) Thanks, John

John Goerzen
type CFilter = Content -> [Content]
Try as I might, I could not figure out a nice way to integrate I/O into this system. A simple IO CFilter wouldn't work, since there has to be input available when it runs. Content -> IO [Content] didn't work either, since the IO ripples up all the way to the top, messing up the nice code everywhere.
I have been toying with the idea that the CFilter type is nearly a monad itself (return = keep, bind = o). If it can be re-formulated as such, then there is a possibility that one could use monad transformers (liftM etc) to compose the CFilter and IO monads easily. However, recasting the HaXml combinator library monadically is rather more work than I have time for at the moment... Regards, Malcolm

On Fri, Jan 21, 2005 at 02:53:04PM +0000, John Goerzen wrote:
I've been playing with HaXmL lately. I've had a need to convert one XML document to another, and HaXmL was very nice for that.
Along the way, I've discovered that I need to do some I/O as part of the conversion (specifically due to timezone-related calculations). Much of HaXML is based around the CFilter type:
type CFilter = Content -> [Content]
That is, most of the stuff one does in HaXML is a function with that type.
Try as I might, I could not figure out a nice way to integrate I/O into this system. A simple IO CFilter wouldn't work, since there has to be input available when it runs. Content -> IO [Content] didn't work either, since the IO ripples up all the way to the top, messing up the nice code everywhere.
If the timezone-related stuff is simple enough, you could perhaps use a function create_my_cfilter :: IO CFilter which does IO stuff to find the timezone, and then returns a pure function that uses that TZ info. -- David Roundy http://civet.berkeley.edu/droundy/

At 14:53 21/01/05 +0000, John Goerzen wrote:
I've been playing with HaXmL lately. I've had a need to convert one XML document to another, and HaXmL was very nice for that.
Along the way, I've discovered that I need to do some I/O as part of the conversion (specifically due to timezone-related calculations). Much of HaXML is based around the CFilter type:
<later> I just saw David Roundy's response, and think that's way better than my approach (below). </later> In my modifications to HaXml [1], in re-working the external entity inclusion, I did indeed resort to using unsafePerformIO (which may be original HaXml, I don't recall). Later, I thought of a cleaner approach which would be to make the XML parsing parameterized (somehow, I forget the details right now) on a monadic function for entity retrieval. For calling functions that don't want to be forced into the IO monad, use an identity monad, which in turn would not allow external entities, otherwise use an IO function. This approach is specialized to a particular use of IO, and requires modifying the HaXml code. When I get time (not in the foreseeable future), it's a change I'd like to apply to get rid of the unsafePerformIO. I already have alternative parsing functions with/without external entity support to distinguish internal and external XML subset cases. I haven't actually worked out the details for using a monad, so I could be completely deluded here. [1] http://www.ninebynine.org/Software/HaskellUtils/HaXml-1.12/ Specifically: http://www.ninebynine.org/Software/HaskellUtils/HaXml-1.12/src/Text/XML/HaXm... which currently has alternative functions peNullResolver and peExtResolver to handle cases that are permitted/not permitted to perform IO, calling in turn: http://www.ninebynine.org/Software/HaskellUtils/HaXml-1.12/src/Text/XML/HaXm... http://www.ninebynine.org/Software/HaskellUtils/HaXml-1.12/src/Text/XML/HaXm... #g -- At 15:17 20/01/05 -0500, Mark Carroll wrote:
I tried writing a little command-line utility to find the relative path of one thing from another thing (with Unix-like systems in mind). For example,
At 14:53 21/01/05 +0000, John Goerzen wrote:
I've been playing with HaXmL lately. I've had a need to convert one XML document to another, and HaXmL was very nice for that.
Along the way, I've discovered that I need to do some I/O as part of the conversion (specifically due to timezone-related calculations). Much of HaXML is based around the CFilter type:
type CFilter = Content -> [Content]
That is, most of the stuff one does in HaXML is a function with that type.
Try as I might, I could not figure out a nice way to integrate I/O into this system. A simple IO CFilter wouldn't work, since there has to be input available when it runs. Content -> IO [Content] didn't work either, since the IO ripples up all the way to the top, messing up the nice code everywhere.
I finally resorted to unsafePerformIO to get it done. But I'd like to know the proper solution. I do hope that this is not it :-)
Thanks, John
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
------------ Graham Klyne For email: http://www.ninebynine.org/#Contact
participants (4)
-
David Roundy
-
Graham Klyne
-
John Goerzen
-
Malcolm Wallace