Reputation: 48581
Difference between `data` and `newtype` in Haskell and a couple other questions address the general differences between data and newtype. My question is a very specific one. If G
is some type, is there any difference between
data T = T !G
and
newtype T = T G
?
They appear to have the same strictness properties, and I don't see why the compiler would have any reason to compile them differently, but maybe I'm missing something.
Upvotes: 6
Views: 528
Reputation: 9414
I'm going to answer a slightly different question: "does newtype
add any semantic functionality to Haskell?". I believe the answer is "no".
Suppose we have data Td = Td !G
and newtype Tn = Tn G
. Then
Td
and Tn
have exactly the same inhabitants, i.e. the inhabitants of G
g
they "contain" is forcedcase
but this is only syntactic. There is a direct correspondance between the two versions.The following table explains how a newtype
Tn
can be replaced by a data
Td
in a case
statement. There's also a translation back the other way.
Tn Td
case tn of _ -> ... case td of _ -> ...
case tn of Tn _ -> ...
case tn of Tn x -> ... x ... let x1 = case tn of Td x -> x in ... x1 ...
case tn of x -> ... x ... case td of x -> ... x ...
case tn of Tn x -> x `seq` ... case td of Td _ -> ...
case tn of Tn x -> x `seq` ... x ... case td of Td x -> ... x ...
So semantically speaking I believe Haskell could have avoided adding newtype
. Syntactically speaking newtype maybe makes case
statements a less awkward, that's all.
Upvotes: 2
Reputation: 43309
The major difference is in how it's gonna get compiled. All data
declarations introduce memory overhead, while newtype
don't.
Here's an output of a memory footprint measurement library.
import GHC.DataSize
data A = A !Int
newtype B = B Int
main = do
print =<< (recursiveSize $! A 1)
print =<< (recursiveSize $! B 1)
print =<< (recursiveSize $! 1)
output:
32
16
16
Another difference is mentioned by Shachaf in the first comment.
Upvotes: 3