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 Elem
data constructor used to take a Name
, which is just a type synonym for String
. Sometime between that and version 1.22.3, however, it was changed to take a QName
, which is a custom data type.
It therefore makes sense that using isPrefixOf
on 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.
I recently had success integrating Haskell and Python using the Apache Thrift project. The Thrift compiler works off a data and service definition file to generate the code in the necessary languagues to create client and servers that seamlesslessly pass messages to each other.
Untested fix:
1) Change the line that says import Data.List(isPrefixOf) to
import qualified Data.List(isPrefixOf) as List
2) Add this code:
isPrefixOf (N n) = List.isPrefixOf n
isPrefixOf (QN _ n) = List.isPrefixOf n
Im not sure if this gives the intended behaviour for qualified names though.
精彩评论