Both newtype
and the single-constructor data
introduce a single value constructor, but the value constructor introduced by newtype
is strict and the value constructor introduced by data
is lazy. So if you have
data D = D Int
newtype N = N Int
Then N undefined
is equivalent to undefined
and causes an error when evaluated. But D undefined
is not equivalent to undefined
, and it can be evaluated as long as you don’t try to peek inside.
Couldn’t the compiler handle this for itself.
No, not really—this is a case where as the programmer you get to decide whether the constructor is strict or lazy. To understand when and how to make constructors strict or lazy, you have to have a much better understanding of lazy evaluation than I do. I stick to the idea in the Report, namely that newtype
is there for you to rename an existing type, like having several different incompatible kinds of measurements:
newtype Feet = Feet Double
newtype Cm = Cm Double
both behave exactly like Double
at run time, but the compiler promises not to let you confuse them.