In the Rename Data Types section of a report
Unlike algebraic data types, the constructor newtype N does not access, so N ⊥ matches ⊥.
Here
Sum ⊥ = ⊥
therefore, the weak head normal form of the new type is WHNF of the wrapped type, and
Sum (lengthyComputation :: Int) `using` rseq
evaluates lengthyComputation (when evaluating the whole expression, simple binding
let x = Sum (lengthyComputation :: Int) `using` rseq
of course not, but it's the same without the newtype constructor).
definition of equations for seq
seq ⊥ b = ⊥ seq ab = b, if a ≠ ⊥
and therefore
seq (Sum ⊥) b = ⊥
and in
seq (lengthyComputaton :: Int) b
seq needs to find out (sorry for the anthropomorphism) whether lengthyComputation :: Int ⊥ or not. To do this, it must evaluate lengthyComputation :: Int .
Re update:
newtype not used, this means that the constructor is not a constructor of values semantically (only syntactically). Pattern matching in the newtype constructor, unlike pattern matching in the data constructor, is not strict. Considering,
newtype Foo a = Foo { unFoo :: a } -- record syntax for convenience below
a "pattern matching"
function :: Foo a -> Bar function (Foo x) = whatever x
completely equivalent
function y = let x = unFoo y in whatever x
A match always succeeds and does not value anything. The constructor only enforces the type , and "pattern matching" on it does not loop the value type.
seq is magic; it cannot be implemented in Haskell. You can write a function that does the same as seq for the data type, for example, your seqMaybe above, in Haskell, but not for the (polymorphic) newtype , because the "pattern matching" in the newtype constructor is not strict. You will have to map the constructor of the wrapped type, but for the polymorphic newtype you don't have them.