Haskellのnewtype
代数的データ型を用いて新たな型を定義する
元の型とは全くの別物になる
パフォーマンスに影響を与えない
コンストラクタに包んだり出したりするオーバヘッドがかからない
ghci(hs)ghci> newtype N = N Int
ghci> let n = N (1+1)
ghci> :sprint n
n = _
ghci> seq n ()
()
ghci> :sprint n
n = N 2
そのため !
を使った定義はできない
(元々なっているので)
再帰的定義もできる
例.hsnewtype Fix f = Fix (f (Fix f))
制限がある
値コンストラクタは1つだけ
hsnewtype Volume = Volume Double -- ok
newtype A = B String | C Int -- ng
その値コンストラクタが持てるフィールドも1つだけ
hsnewtype Size = Size { unSize :: Int } -- ok
newtype Point = Point -- ng
{ pointX :: Int
, pointY :: Int
}
newtype
は1つしか値コンストラクタを取らない
そのため、パターンマッチにおけるパターンは1つしかない
このルールは、ランタイムでtypeと同じ挙動をさせるために必要
このルールによって、dataと少し異なる挙動をすることがある
例えば以下の様なコード
data
と newtype
を使って同じ様な構造の型と関数を定義する
hsdata D a = D a
f (D _) = "hello"
newtype N a = N a
g (N _) = "hello"
これらの関数を undefined
に適用する
hsf undefined -- error
g undefined -- "hello"
newtype
の定義は、ランタイム上で見れば、以下の様に定義しているのと同じ
hstype N a = a
g _ = "hello"
だからerrorにならない
derivingで型クラスのインスタンスにするときは、中身の既存の型がその型クラスのインスタンスである必要がある
hsnewtype ZipList a = ZipList { getZipList :: [a] }
-- こう使える
getZipList $ ZipList "hoge"

p.261
参考
typeより、エラーメッセージがわかりやすくなる
ref