2013-08-16 109 views
5

Tôi đang cố gắng tạo tuần tự hóa/deserialization bằng cách đọc và hiển thị (không phải là vấn đề), nhưng có thể mở rộng theo nghĩa là dữ liệu có thể được mở rộng (nhưng không bị thu hẹp) .Nối tiếp có thể mở rộng trong Haskell

Giả sử tôi có loại này:

data Foo = { bar :: Int } deriving (Show, Read) 

Và danh sách:

foos = [Foo 1, Foo 2] 

tôi có thể dễ dàng deserialize nó thành một tập tin:

hPutStrLn fileHand . ppShow $ foos 

Sau đó, tôi có thể serialize nó trở lại :

!str <- hGetContents fileHand 
let foosFromFile = fromMaybe [] $ (readMaybe :: String -> Maybe [Foo]) str 

Nhưng giả sử rằng vài tháng sau, tôi muốn thêm trường 'baz' vào loại Foo . Việc serialization trực tiếp từ tập tin định dạng cũ sẽ không còn làm việc với đọc, tôi sẽ cần phải chuyển đổi các tập tin (mà tôi không thực sự muốn).

Vì vậy, có một giải pháp thanh lịch (không đặt một phiên bản rõ ràng trong chính chương trình) để vẫn tuần tự hóa dữ liệu từ một tệp và điền vào các trường bị thiếu với các giá trị mặc định không? Có lẽ một số loại thủ thuật?

Cảm ơn.

Trả lời

2

Có. Chỉ cần thêm một lĩnh vực đa hình:

data Foo a = { bar :: Int, extra :: a } deriving (Show, Read) 

Sau đó xác định một trường hợp serialization với ràng buộc là a phải serializable:

instance (Serialize a) => Serialize (Foo a) where ... 

Khi bạn không sử dụng các trường bổ sung, chỉ cần chèn một () vào nó , kể từ () là có thể tuần tự tuần tự (và đã có phiên bản Serialize).

Chỉnh sửa: Rất tiếc, chỉ cần nhận ra bạn đang nói về việc in ấn khá. Các giải pháp tương đương là để xác định một lớp kiểu như thế này:

class PrettyPrint a where 
    pp :: a -> String 

instance PrettyPrint() where 
    pp() = "" 

instance (PrettyPrint a) => PrettyPrint (Foo a) where 
    pp = ... -- You fill this in 
9

này có thể không phải những gì bạn đang tìm kiếm kể từ khi bạn muốn tránh phiên bản rõ ràng nhưng tôi vẫn muốn chỉ ra safecopy là Go- để giải pháp cho serialization phiên bản và ít nhất làm cho nó hơi đau.

Tôi không nghĩ rằng có cách nào để sử dụng mặc định ShowRead trường trong khi hỗ trợ thêm một số lượng tùy ý các lĩnh vực mới, nhưng bạn có thể tất nhiên viết riêng Read dụ của bạn bằng tay mà xử lý các lĩnh vực kỷ lục mất tích. Tuy nhiên, tôi nghĩ rằng đó là mất thời gian và dễ bị lỗi hơn là chỉ sử dụng safecopy.

+0

Tôi chưa bao giờ nghe nói về SafeCopy. Tiện lợi :-) – luqui

+0

+1 để chụp an toàn. Chắc chắn sẽ sử dụng nó. – insitu

3

Muốn có thể thay đổi bố cục dữ liệu trong khi vẫn có thể truy cập nội dung của bạn, hãy thực hiện một số động tác để phát minh hệ thống quản lý cơ sở dữ liệu. Bạn đã xem xét việc bỏ dữ liệu của mình vào một bảng SQLite đơn giản chưa?Nó có thể là quá mức cần thiết cho những gì bạn đang cố gắng làm, nhưng nó có một số lợi thế:

  • Gần như chắc chắn hiệu quả hơn mã hóa dựa trên văn bản.
  • Bạn vẫn có thể dễ dàng đọc từ bên ngoài ứng dụng của mình (ví dụ: để kiểm tra xem đã lưu đúng điều gì chưa).
  • "Chuyển đổi tệp" bây giờ sẽ tính một truy vấn SQL đơn giản.
  • Nếu bạn tránh sử dụng * làm công cụ chọn cột, mã cũ của bạn vẫn có thể đọc nội dung được tạo bởi các phiên bản ứng dụng mới hơn. (I.e., chuyển tiếp khả năng tương thích cũng như ngược).
  • Ngoài ra, bạn có thể đọc viết một số mã bản mẫu đơn giản để đọc lược đồ DB và cung cấp các giá trị mặc định cho bất kỳ cột nào chưa tồn tại.

Tôi không biết điều này có phù hợp với trường hợp của bạn hay không nhưng đáng để suy nghĩ.

4

Tùy thuộc vào trường hợp sử dụng của bạn, bạn cũng có thể sử dụng persistent từ Yesod để duy trì dữ liệu của mình trong cơ sở dữ liệu. Trích dẫn:

Đồng nhất tuân theo nguyên tắc hướng dẫn về an toàn loại và súc tích, cú pháp khai báo. Một số tính năng thú vị khác là:

  • Cơ sở dữ liệu bất khả tri. Có hỗ trợ lớp học đầu tiên cho PostgreSQL, SQLite, MySQL và MongoDB, với sự hỗ trợ CouchDB thử nghiệm trong các tác phẩm.
  • Do không quan hệ trong tự nhiên, chúng tôi đồng thời có thể hỗ trợ nhiều lớp lưu trữ hơn và không bị hạn chế bởi một số tắc nghẽn hiệu suất phát sinh thông qua các kết nối.
  • Một nguồn gây thất vọng lớn trong việc xử lý cơ sở dữ liệu SQL là những thay đổi đối với lược đồ. Persistent có thể tự động thực hiện di chuyển cơ sở dữ liệu.

dai dẳng xử lý những thay đổi trong dữ liệu của bạn cho bạn trong những trường hợp:

Đối với các trường hợp sau đây, nó sẽ tự động thay đổi schema:

  • Các kiểu dữ liệu của một trường đã thay đổi. Tuy nhiên, cơ sở dữ liệu có thể phản đối sửa đổi này nếu dữ liệu không thể dịch được.
  • Một trường đã được thêm. Tuy nhiên, nếu trường không rỗng, không có giá trị mặc định nào được cung cấp (chúng tôi sẽ thảo luận về mặc định sau) và đã có dữ liệu trong cơ sở dữ liệu, cơ sở dữ liệu sẽ không cho phép điều này xảy ra.
  • Một trường được chuyển đổi từ không null thành null. Trong trường hợp ngược lại, Persistent sẽ cố gắng chuyển đổi, tùy thuộc vào sự chấp thuận của cơ sở dữ liệu.
  • Một thực thể hoàn toàn mới được thêm vào.