{-# OPTIONS -fglasgow-exts #-} {-# LANGUAGE UndecidableInstances #-} module NestedDatatypes () where {- We provide an illustrative ScrapYourBoilerplate example for a nested datatype. For clarity, we do not derive the Typeable and Data instances by the deriving mechanism but we show the intended definitions. The overall conclusion is that nested datatypes do not pose any challenge for the ScrapYourBoilerplate scheme. Well, this is maybe not quite true because it seems like we need to allow undecidable instances. -} import Data.Dynamic import Data.Generics -- A nested datatype data Nest a = Box a | Wrap (Nest [a]) -- The representation of the type constructor nestTc = mkTyCon "Nest" -- The Typeable instance for the nested datatype instance Typeable1 Nest where typeOf1 n = mkTyConApp nestTc [] -- The Data instance for the nested datatype instance (Data a, Data [a]) => Data (Nest a) where gfoldl k z (Box a) = z Box `k` a gfoldl k z (Wrap w) = z Wrap `k` w gmapT f (Box a) = Box (f a) gmapT f (Wrap w) = Wrap (f w) toConstr (Box _) = boxConstr toConstr (Wrap _) = wrapConstr gunfold k z c = case constrIndex c of 1 -> k (z Box) 2 -> k (z Wrap) dataTypeOf _ = nestDataType boxConstr = mkConstr nestDataType "Box" [] Prefix wrapConstr = mkConstr nestDataType "Wrap" [] Prefix nestDataType = mkDataType "Main.Nest" [boxConstr,wrapConstr]