2012-04-21 6 views
10

Gói encoding sử dụng HaXml trong tập lệnh xây dựng (trong Setup.hs). Nó xảy ra để sử dụng các bit của giao diện thay đổi giữa HaXml-1.19 và HaXml-1.22. Sẽ rất tuyệt nếu gói mã hóa có thể xây dựng với cả hai phiên bản. Tôi đã cố gắng sử dụng các trick Cabal thường lệ, cụ thể là, làm một cái gì đó giống nhưthay đổi cách Setup.hs được xây dựng

{-# LANGUAGE CPP #-} 
#if MIN_VERSION_HaXml(1,22,0) 
-- HaXml-1.22 code 
#else 
-- HaXml-1.19 code 
#endif 

... nhưng định nghĩa ma thuật không thể tồn tại trước khi gói được cấu hình, và tập tin này đang được xây dựng để thực hiện bước cấu hình tốt. Những lựa chọn của tôi là gì? Có cách nào để thay đổi lệnh gọi cabal-install để biên dịch Setup.hs không? Có cơ chế nào khác để chọn mã có điều kiện để tránh cabal không?

+0

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ì. –

+0

@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ả). –

+0

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) –

Trả lời

4

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)

+0

Điều này có vẻ tuyệt vời. –

2

Dường như không có nhiều nút bấm trong kiểm soát việc biên dịch Setup.hs, do đó, đặt cược tốt nhất của bạn có thể là tạo tệp Setup.hs sơ khai thực hiện kiểm tra phiên bản và sau đó thực hiện Setup.hs thực nó đã tìm ra phiên bản là gì.

Bí quyết khác là tạo thư viện tính tương thích mà tập lệnh Thiết lập của bạn sử dụng, có các thủ thuật phiên bản thích hợp.

Nhưng có thể câu hỏi thực sự cần đặt ra là: tại sao Setup.hs sử dụng thư viện bên ngoài?

+0

Hm, làm thế nào sẽ đưa ra trợ giúp ? Nó sẽ không tạo ra một nỗ lực để xây dựng (cả) thứ mà tôi đang giao? –

+0

Phải, bạn cần phải reinvoke GHC với các định nghĩa vĩ mô thích hợp. –