= GND Pre-GHC-7.8 =
We will ignore the type-safety issues as they have been resolved, instead we'll just look at the module boundary / abstraction issues.
In GHC 7.6 or earlier, assume a library author writes the following `MinList` data type:
{{{
module MinList (
MinList, newMinList, insertMinList,
) where
data MinList a = MinList a [a] deriving (Show)
newMinList :: Ord a => a -> MinList a
newMinList n = MinList n []
insertMinList :: Ord a => MinList a -> a -> MinList a
insertMinList s@(MinList m xs) n | n > m = MinList m (n:xs)
| otherwise = s
}}}
The `MinList` data type has an invariant (that depends on the `Ord` typeclass for the type parameter `a` that `MinList` is instantiated at) that after initialization it doesn't accept any element less than the initial element.
In GHC 7.6 and earlier, we could use GND to violate this invariant:
{{{
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
module Main where
import MinList
class IntIso t where
intIso :: c t -> c Int
instance IntIso Int where
intIso = id
newtype Down a = Down a deriving (Eq, IntIso)
instance Ord a => Ord (Down a) where
compare (Down a) (Down b) = compare b a
fine :: MinList (Down Int)
fine = foldl (\x y -> insertMinList x $ Down y) (newMinList $ Down 0) [-1,-2,-3,-4,1,2,3,4]
unsafeCast :: MinList (Down Int) -> MinList Int
unsafeCast = intIso
bad :: MinList Int
bad = unsafeCast fine
main = do
print bad
}}}
Essentially, through GND we have created the function `unsafeCast :: MinList (Down Int) -> MinList Int`. This is a function we can't write by hand since we don't have access to the `MinList` constructor and so can't "see" into the data type.
== Safe Haskell Pre-GHC-7.8 ==
Due to both the type-safety and abstraction issues, GND was considered unsafe in Safe Haskell.