Giao diện Data.Data
có khả năng (chỉ là về!) Của việc xây dựng và giải mã các giá trị của một loại có thể có hoặc không tồn tại. Thật không may, HaXml dường như không có các trường hợp Data
cho loại của nó và bạn không thể xác định loại vì bạn không thể tham chiếu đến loại có thể hoặc không tồn tại, vì vậy chúng tôi phải sử dụng Mẫu Haskell:
xuất khẩu mô-đun sau qnameCompat
:
{-# LANGUAGE TemplateHaskell #-}
module HaXmlCompat (qnameCompat) where
import Language.Haskell.TH
qnameCompat :: Q [Dec]
qnameCompat = do
mi <- maybeReify "N"
case mi of
Nothing -> sequence [
tySynD (mkName "QName") [] [t| String |],
valD [p| toQName |] (normalB [| id |]) [],
valD [p| fromQName |] (normalB [| Just |]) []]
Just (DataConI n _ _ _) -> do
s <- newName "s"
sequence [
valD [p| toQName |] (normalB (conE n)) [],
funD (mkName "fromQName") [
clause [conP n [varP s]] (normalB (appE [| Just |] (varE s))) [],
clause [ [p| _ |] ] (normalB [| Nothing |]) []]]
Just i -> fail $
"N exists, but isn't the sort of thing I expected: " ++ show i
maybeReify :: String -> Q (Maybe Info)
maybeReify = recover (return Nothing) . fmap Just . reify . mkName
Khi ghép ở cấp cao nhất sử dụng Template Haskell, qnameCompat
sẽ kiểm tra nếu N
tồn tại. Nếu có, nó tạo ra đoạn mã sau:
toQName = N
fromQName (N s) = Just s
fromQName _ = Nothing
Nếu không, sau đây được tạo ra:
type QName = String
toQName = id
fromQName = Just
Bây giờ bạn có thể tạo và giải cấu trúc Element
s, ví dụ sử dụng phần mở rộng ViewPatterns:
myElt :: String -> Element i
myElt = Elem (toQName "elemName") [] []
eltName :: Element i -> String
eltName (Elem (fromQName -> Just n) _ _) = n
ViewPatterns là thuận tiện, nhưng không cần thiết, tất nhiên: sử dụng kết hợp mô hình bình thường về kết quả của fromQName
sẽ làm việc chỉ là tốt.
(Những ý tưởng những gì dẫn tôi để phát triển notcpp package, trong đó bao gồm maybeReify
và một số tiện ích hữu ích khác)
Làm thế nào nghiêm trọng là những thay đổi giao diện? Họ có những thay đổi gì? Có thể mẫu haskell có thể cứu bạn, tùy thuộc vào chúng là gì. –
@benmachine Sự thay đổi thực sự duy nhất là hàm tạo 'Element' bây giờ lấy một giá trị kiểu' data QName = N String | SomethingIDon'tCareAbout' thay vì 'String'. File 'Setup.hs' sử dụng hàm tạo' Element' cả hai như là một hàm (luôn luôn với một 'String') và cho phù hợp với mẫu (đôi khi với một chuỗi' Chuỗi' và đôi khi với một mẫu biến bắt tất cả). –
Vì vậy, nó sẽ đủ nếu bạn có chức năng 'toQName' và' fromQName' sao cho khi 'QName' tồn tại,' toQName = N' và 'fromQName' biến' N s' thành 'Chỉ s' (và bất kỳ thứ gì khác thành' Không có gì '), trong khi khi' QName' không tồn tại, 'toQName = id' và' fromQName = Just'? Sau đó, bạn có thể làm những gì bạn muốn với các mẫu xem? Tôi nghĩ rằng 'toQName' và' fromQName' có thể được định nghĩa với mẫu haskell, sử dụng các ý tưởng tương tự như trong gói [notcpp] của tôi (http://hackage.haskell.org/package/notcpp) –