I’m looking for a solution to interchange data between Haskell and Java/Scala/C# code. Currently, I’m thinking about using XML. Ideally, I’d like the XML schema to be generated from my Haskell datatypes. My first try was HaXml 1.22.2, DrIFT 2.2.2. All on GHC 7.0.3. There is the following snippet:
import Data.List (isPrefixOf)
import Text.XML.HaXml.XmlContent
import Text.XML.HaXml.Types
import Text.XML.HaXml.Pretty (document)
data MyType = A | B String deriving (Eq, Show)
{-! derive : XmlContent !-} -- this line is for DrIFT
out of this file, DrIFT produces:
{- Generated by DrIFT (Automatic class derivations for Haskell) -}
{-# LINE 1 "ts.hs" #-}
import Data.List (isPrefixOf)
import Text.XML.HaXml.XmlContent
import Text.XML.HaXml.Types
import Text.XML.HaXml.Pretty (document)
data MyType = A | B String deriving (Eq, Show)
{-! derive : XmlContent !-} -- this line is for DrIFT
{-* Generated by DrIFT : Look, but Don't Touch. *-}
instance HTypeable MyType where
toHType v =
Defined "MyType" [] [Constr "A" [] [],Constr "B" [] [toHType aa]]
where
(B aa) = v
instance XmlContent MyType where
parseContents = do
{ e@(Elem t _ _) <- elementWith (flip isPrefixOf) ["B","A"]
; case t of
_ | "B" `isPrefixOf` t -> interior e $ fmap B parseContents
| "A" `isPrefixOf` t -> interior e $ return A
}
toContents v@A =
[mkElemC (showConstr 0 (toHType v)) []]
toContents v@(B aa) =
[mkElemC (showConstr 1 (toHType v)) (toContents aa)]
-- Imported from other files :-
Compiling this code with GHC produces an error message:
19:32:
Couldn't match expected type `[Char]' with actual type `QName'
In the second argument of `isPrefixOf', namely `t'
In the expression: "B" `isPrefixOf` t
In a stmt of a pattern guard for
a case alternative:
"B" `isPrefixOf` t
Is it a problem with tooling or I’m doing something wrong? How to resolve this problem?
Diggin around in the Hackage documentation for older versions of HaXml reveals that in version 1.20.2 and earlier, the
Elemdata constructor used to take aName, which is just a type synonym forString. Sometime between that and version 1.22.3, however, it was changed to take aQName, which is a custom data type.It therefore makes sense that using
isPrefixOfon element names would be valid for older versions, but invalid for newer versions.From the upload dates of these versions, this happened sometime during the last year, while DrIFT does not appear to have been updated since 2009.
You should probably notify the DrIFT maintainer of this. In the meanwhile, you can work around it by using an older version of HaXml, or by writing the instances yourself. You should be able to use the incorrect generated instances as a starting point.