
1) This might be the code written by someone using your library/framework. In which case it would know about A and B.
Then it's up to me to define and document whatever strictness properties I want for my constructors.
Of course. But it's NOT up to you to restrict the user from using whatever techniques xe wants
in existing code. Of course that won't work. But for *new* datatypes choosing one rather than the other gives no difference in terms of denotational semantics.
If it makes the difference for the old code, then it would make the difference for the new code as well.
2) It might be generated by the Template Haskell — which is free to use whatever constructor is fed into it.
OK, so show me what goes wrong!
I hate it. OK, here we go: {-# LANGUAGE TemplateHaskell #-} module TH where import Language.Haskell.TH check :: Name -> ExpQ check c = [|let x = case x of $(conP c [[p|_|]]) -> $(conE c) 1 in x|] {-# LANGUAGE TemplateHaskell #-} module Use where import TH newtype A = A Int deriving Show data B = B !Int deriving Show a = $(check 'A) b = $(check 'B) Prelude> :load "Use.hs" [1 of 2] Compiling TH ( TH.hs, interpreted ) [2 of 2] Compiling Use ( Use.hs, interpreted ) Use.hs:6:1: Warning: Top-level binding with no type signature: a :: A Use.hs:7:1: Warning: Top-level binding with no type signature: b :: B Ok, modules loaded: TH, Use. *Use> a A 1 *Use> b C-c C-cInterrupted.