Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Strict single-constructor single-field data declaration vs. newtype

Tags:

haskell

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.

like image 613
dfeuer Avatar asked Jan 24 '14 08:01

dfeuer


2 Answers

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.

like image 190
Nikita Volkov Avatar answered Nov 13 '22 00:11

Nikita Volkov


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
  • When forced to WHNF both behave in the same way: the g they "contain" is forced
  • They differ in how they interact with case 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.

like image 33
Tom Ellis Avatar answered Nov 13 '22 00:11

Tom Ellis