Perbedaan antara `data` dan` tipe baru` di Haskell

191

Apa bedanya ketika saya menulis ini?

data Book = Book Int Int

melawan

newtype Book = Book (Int, Int) -- "Book Int Int" is syntactically invalid
ewggwegw
sumber
Anda harus melakukan pencarian, pertanyaan ini sudah dijawab. stackoverflow.com/questions/2649305/…
tehman
Terkait dengan stackoverflow.com/questions/2649305/…
Don Stewart
Juga terkait: penggunaan untuk tipe baru: stackoverflow.com/questions/991467/…
Don Stewart
25
Catatan yang newtype Book = Book Int Inttidak valid. Namun Anda dapat, newtype Book = Book (Int, Int)seperti yang dicatat oleh don di bawah ini.
Edward KMETT

Jawaban:

241

Pertanyaan bagus!

Ada beberapa perbedaan utama.

Perwakilan

  • A newtypemenjamin bahwa data Anda akan memiliki representasi yang sama persis saat runtime, seperti tipe yang Anda bungkus.
  • Sementara datamendeklarasikan struktur data baru saat runtime.

Jadi titik kunci di sini adalah bahwa konstruksi untuk newtype dijamin akan dihapus pada waktu kompilasi.

Contoh:

  • data Book = Book Int Int

data

  • newtype Book = Book (Int, Int)

tipe baru

Perhatikan bagaimana ia memiliki representasi yang sama persis dengan a (Int,Int), karena Bookkonstruktor dihapus.

  • data Book = Book (Int, Int)

tuple data

Memiliki Bookkonstruktor tambahan tidak ada dalam newtype.

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

masukkan deskripsi gambar di sini

Tidak ada petunjuk! Dua Intbidang adalah bidang berukuran kata tanpa kotak di dalam Bookkonstruktor.

Tipe data aljabar

Karena kebutuhan ini untuk menghapus konstruktor, newtypehanya berfungsi ketika membungkus tipe data dengan konstruktor tunggal . Tidak ada gagasan tentang tipe baru "aljabar". Artinya, Anda tidak dapat menulis jenis baru yang setara dengan, katakanlah,

data Maybe a = Nothing
             | Just a

karena memiliki lebih dari satu konstruktor. Anda juga tidak bisa menulis

newtype Book = Book Int Int

Kekerasan

Fakta bahwa konstruktor dihapus mengarah ke beberapa perbedaan yang sangat halus dalam keketatan antara datadan newtype. Secara khusus, datamemperkenalkan tipe yang "diangkat", yang berarti, pada dasarnya, ia memiliki cara tambahan untuk mengevaluasi ke nilai terbawah. Karena tidak ada konstruktor tambahan saat runtime dengannewtype , properti ini tidak berlaku.

Pointer ekstra di dalam Bookto (,)constructor memungkinkan kita untuk memasukkan nilai terbawah.

Akibatnya, newtypedan datamemiliki sifat keketatan yang sedikit berbeda, seperti yang dijelaskan dalam artikel wiki Haskell .

Buka kotak

Tidak masuk akal untuk membuka kotak komponen newtype, karena tidak ada konstruktor. Meskipun sangat masuk akal untuk menulis:

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

menghasilkan objek runtime dengan Tkonstruktor, dan Int#komponen. Anda hanya mendapatkan telanjang Intdengan newtype.


Referensi :

Don Stewart
sumber
2
Saya masih berpikir saya tidak akan melewatkan sesuatu jika tidak ada "tipe baru" di Haskell. Perbedaan yang halus menambah kerumitan pada bahasa yang sepertinya tidak
berguna
14
Perbedaannya sangat berguna untuk alasan kinerja. Karena konstruktor tipe baru dihapus pada waktu kompilasi, mereka tidak memaksakan penalti kinerja runtime yang dilakukan oleh konstruktor data. Tetapi mereka masih memberi Anda semua manfaat dari tipe yang benar-benar berbeda dan abstraksi apa pun yang ingin Anda kaitkan dengannya. Misalnya, ada dua cara berbeda tipe data daftar dapat membentuk monad. Satu dibangun ke dalam bahasa, tetapi jika Anda ingin menggunakan yang lain, jenis baru akan menjadi cara untuk pergi.
mightybyte
Penjelasan hebat! Apa yang saya tidak mengerti adalah jika newtypedihapus setelah kompilasi dan runtime menggunakan representasi yang sama untuk tipe lama dan baru, bagaimana kita masih dapat mendefinisikan instance untuk tipe lama dan baru? Bagaimana cara runtime memahami instance mana yang digunakan?
damluar
3
@damluar Semua tipe dihapus saat runtime, mereka semua sepenuhnya diselesaikan pada waktu kompilasi, dan selama kompilasi newtypejelas belum terhapus.
titik koma
3
@damlaur Saya pernah memiliki pertanyaan yang sama seperti Anda. Ketika orang mengatakan jenis dihapus, mereka menghilangkan untuk menyebutkan bahwa satu hal TIDAK dihapus, yang merupakan kata memori yang digunakan untuk pencarian kamus untuk memutuskan metode contoh apa yang digunakan untuk sepotong data tertentu. Orang-orang berpendapat bahwa kata ini bukan "tipe", yang saya pikir tergantung pada perspektif Anda, tetapi begitulah.
Gabriel L.