web-dev-qa-db-ja.com

Haskellの `data`と` newtype`の違い

これを書くときの違いは何ですか?

data Book = Book Int Int

versus

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

いい質問です!

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

表現

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

そのため、ここで重要なのは、newtypeのコンストラクトがコンパイル時に確実に消去されることです。

例:

  • _data Book = Book Int Int_

data

  • newtype Book = Book (Int, Int)

newtype

Bookコンストラクターが消去されるため、_(Int,Int)_とまったく同じ表現になることに注意してください。

  • data Book = Book (Int, Int)

data Tuple

Bookに存在しない追加のnewtypeコンストラクターがあります。

  • _data Book = Book {-# UNPACK #-}!Int {-# UNPACK #-}!Int_

enter image description here

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

代数的データ型

このため、コンストラクターを消去する必要があるため、newtypeは、データ型を単一のコンストラクターでラップする場合にのみ機能します。 「代数」ニュータイプの概念はありません。つまり、たとえば、と同等の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#_コンポーネントを持つランタイムオブジェクトを生成します。 Intで裸のnewtypeを取得するだけです。


参照

224
Don Stewart