1. ホーム

[解決済み】Haskell の `data` と `newtype` の違いについて

2022-04-17 07:59:52

質問

このように書くと何が違うのでしょうか?

data Book = Book Int Int

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

解決方法は?

いい質問ですね。

いくつかの重要な違いがあります。

表現方法

  • A newtype は、ラップした型と全く同じ表現を実行時に持つことを保証します。
  • 一方 data は、実行時に全く新しいデータ構造を宣言します。

つまり、ここでの重要なポイントは newtype は、コンパイル時に消去されることが保証されています。

  • data Book = Book Int Int

  • newtype Book = Book (Int, Int)

と全く同じ表現をしていることに注意してください。 (Int,Int) というのは Book のコンストラクタは消去されます。

  • data Book = Book (Int, Int)

を追加しています。 Book には存在しないコンストラクタです。 newtype .

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

ポインターがない!?2つの Int フィールドは、ボックス化されていないワードサイズのフィールドで Book コンストラクタを使用します。

代数的なデータ型

このようにコンストラクタを消去する必要があるため newtype でデータ型をラップするときのみ機能します。 単一のコンストラクタ . 代数的な新型の概念はありません.つまり,例えば,次のようなものに相当する新しい型を書くことはできません.

data Maybe a = Nothing
             | Just a

は複数のコンストラクタを持っているからです。また

newtype Book = Book Int Int

厳密性

コンストラクタが消去されることで、以下のように非常に微妙な厳密性の違いが生じます。 datanewtype . 特に data つまり、本質的に、底値に評価する方法が追加されているのです。には実行時に追加のコンストラクタはありません。 newtype という性質があるため、この性質は成り立ちません。

の余分なポインタは Book から (,) のコンストラクタで底値を入れることができます。

その結果 newtypedata のように、厳密性のプロパティが若干異なります。 は、Haskell wiki の記事 .

アンボックス

のコンポーネントをアンボックス化することは意味がありません。 newtype コンストラクタがないためです。と書くのは全く合理的ですが

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

を持つランタイムオブジェクトを生成します。 T コンストラクタと Int# コンポーネントを使用します。あなたはただ、素の Intnewtype .


参考文献 :