What about phantom types?
{-# LANGUAGE KindSignatures, DataKinds #-} data IsNormalized = Normalized | NotNormalized data Sum (n :: IsNormalized) = Value Int | Sum (Sum n) (Sum n)
You could still say
instance MyClass (Sum n) where…
but you could also write
normalizeSum :: Sum NotNormalized -> Sum Normalized -- or even create a class with two inhabitants for this instance Eq (Sum NotNormalized) where (==) = (==) `on` normalizeSum instance Eq (Sum Normalized) where … -- real implementation
It's not ideal. For example if you want to sort a list, it would
still be better to normalize the whole list before sorting, but at
least you could still use the other operators afterwards without a
"denormalization" step. So maybe it would help reduce some
boilerplate?
Cheers,
MarLinn