Sự khác biệt giữa `data` và` newtype` trong Haskell


191

Sự khác biệt khi tôi viết này là gì?

data Book = Book Int Int

đấu với

newtype Book = Book (Int, Int) -- "Book Int Int" is syntactically invalid

Bạn nên thực hiện một số tìm kiếm xung quanh, câu hỏi này đã được trả lời. stackoverflow.com/questions/2649305/ từ
tehman


Cũng liên quan: sử dụng cho newtype: stackoverflow.com/questions/991467/
Don Stewart

25
Lưu ý rằng newtype Book = Book Int Intkhông hợp lệ. Tuy nhiên, bạn có thể có newtype Book = Book (Int, Int)ghi chú của dons dưới đây.
Edward KMett

Câu trả lời:


241

Câu hỏi tuyệt vời!

Có một số khác biệt chính.

Đại diện

  • Một newtypeđảm bảo rằng dữ liệu của bạn sẽ có cùng một đại diện chính xác trong thời gian chạy, như kiểu mà bạn bọc.
  • Trong khi datatuyên bố một cấu trúc dữ liệu hoàn toàn mới trong thời gian chạy.

Vì vậy, điểm quan trọng ở đây là cấu trúc cho newtypeđược đảm bảo sẽ bị xóa trong thời gian biên dịch.

Ví dụ:

  • data Book = Book Int Int

dữ liệu

  • newtype Book = Book (Int, Int)

loại mới

Lưu ý làm thế nào nó có đại diện chính xác như a (Int,Int), vì hàm Booktạo bị xóa.

  • data Book = Book (Int, Int)

bộ dữ liệu

Có một nhà Bookxây dựng bổ sung không có mặt trong newtype.

  • data Book = Book {-# UNPACK #-}!Int {-# UNPACK #-}!Int

nhập mô tả hình ảnh ở đây

Không có con trỏ! Hai Inttrường là các trường có kích thước từ không có hộp trong hàm Booktạo.

Các kiểu dữ liệu đại số

Do điều này cần phải xóa hàm tạo, nên newtypechỉ hoạt động khi gói một kiểu dữ liệu với một hàm tạo duy nhất . Không có khái niệm về các kiểu mới "đại số". Đó là, bạn không thể viết một loại mới tương đương với, nói,

data Maybe a = Nothing
             | Just a

vì nó có nhiều hơn một constructor. Bạn cũng không thể viết

newtype Book = Book Int Int

Nghiêm khắc

Việc các nhà xây dựng bị xóa dẫn đến một số khác biệt rất tinh tế về mức độ nghiêm ngặt giữa datanewtype. Cụ thể, datagiới thiệu một loại "nâng", về cơ bản, có nghĩa là nó có một cách bổ sung để đánh giá giá trị dưới cùng. Vì không có hàm tạo bổ sung nào trong thời gian chạy với newtype, thuộc tính này không giữ.

Đó là con trỏ phụ trong Bookđể (,)xây dựng cho phép chúng ta đặt một giá trị đáy trong.

Kết quả là, newtypedatacó các thuộc tính nghiêm ngặt hơi khác nhau, như được giải thích trong bài viết wiki Haskell .

Bỏ hộp

Không có ý nghĩa để bỏ hộp các thành phần của a newtype, vì không có hàm tạo. Trong khi nó là hoàn toàn hợp lý để viết:

data T = T {-# UNPACK #-}!Int

mang lại một đối tượng thời gian chạy với một hàm Ttạo và một Int#thành phần. Bạn chỉ cần có một trần Intvới newtype.


Tài liệu tham khảo :


2
Tôi vẫn không nghĩ rằng mình sẽ bỏ lỡ điều gì đó nếu không có "newtype" trong Haskell. Sự khác biệt tinh tế làm tăng thêm sự phức tạp cho ngôn ngữ dường như không xứng đáng với tôi ...
martingw

14
Sự khác biệt là rất hữu ích cho lý do hiệu suất. Vì các hàm tạo newtype bị xóa trong thời gian biên dịch, chúng không áp dụng hình phạt hiệu năng thời gian chạy mà một hàm tạo dữ liệu thực hiện. Nhưng họ vẫn cung cấp cho bạn tất cả những lợi ích của một loại hoàn toàn khác biệt và bất kỳ trừu tượng nào bạn muốn liên kết với nó. Chẳng hạn, có hai cách khác nhau mà kiểu dữ liệu danh sách có thể tạo thành một đơn nguyên. Một cái được tích hợp vào ngôn ngữ, nhưng nếu bạn muốn sử dụng ngôn ngữ kia, một loại mới sẽ là cách để đi.
mightybyte

Giải thích tuyệt vời! Điều tôi không hiểu là nếu newtypebị xóa sau khi biên dịch và thời gian chạy sử dụng cùng một đại diện cho các loại cũ và mới, làm thế nào chúng ta vẫn có thể xác định các thể hiện cho cả loại cũ và loại mới? Làm thế nào thời gian chạy có thể hiểu trường hợp nào để sử dụng?
damluar

3
@damluar Tất cả các loại được xóa trong thời gian chạy, tất cả chúng đều được giải quyết hoàn toàn tại thời gian biên dịch và trong quá trình biên dịch newtyperõ ràng là chưa bị xóa.
dấu chấm phẩy

3
@damlaur Tôi đã từng có câu hỏi tương tự như bạn. Khi mọi người nói rằng các loại đã bị xóa, họ sẽ bỏ qua đề cập rằng một thứ không bị xóa, đó là một từ bộ nhớ được sử dụng để tra cứu từ điển để quyết định sử dụng phương thức cá thể nào cho một phần dữ liệu nhất định. Mọi người tranh luận rằng từ này không phải là một "loại", mà tôi nghĩ phụ thuộc vào quan điểm của bạn, nhưng bạn đi.
Gabriel L.
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.