{-# LANGUAGE DataKinds #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE TypeOperators #-} {-# LANGUAGE UndecidableInstances #-} module Data.Barbie.Internal.Classification ( BarbieType(..) , GClassifyBarbie , ClassifyBarbie ) where import Data.Barbie.Internal.Generics(Target, RecUsage(..), NonRec(..), RecRep, W) import Data.Barbie.Internal.Tags(F) import GHC.Generics data BarbieType = NoBarbie -- ^ The parameter is never used. | WearBarbie -- ^ The parameter is used, and always under a 'Wear'. | NonWearBarbie -- ^ The parameter is used, never under a 'Wear'. | MixedBarbie -- ^ THe parameter is used, sometimes under a 'Wear', somtimes not. type family MergeBarbieType l r where MergeBarbieType 'NoBarbie r = r MergeBarbieType l 'NoBarbie = l MergeBarbieType 'MixedBarbie _ = 'MixedBarbie MergeBarbieType _ 'MixedBarbie = 'MixedBarbie MergeBarbieType x x = x MergeBarbieType _l _r = 'MixedBarbie type family GClassifyBarbie rep where GClassifyBarbie (M1 _i _c x) = GClassifyBarbie x GClassifyBarbie V1 = 'NoBarbie GClassifyBarbie U1 = 'NoBarbie GClassifyBarbie (l :*: r) = MergeBarbieType (GClassifyBarbie l) (GClassifyBarbie r) GClassifyBarbie (l :+: r) = MergeBarbieType (GClassifyBarbie l) (GClassifyBarbie r) GClassifyBarbie (K1 R (NonRec (Target (W F) a))) = 'WearBarbie GClassifyBarbie (K1 R (NonRec (Target F a))) = 'NonWearBarbie GClassifyBarbie (K1 R (NonRec (b (Target F)))) = GClassifyBarbie (Rep (b (Target F))) GClassifyBarbie (K1 R (RecUsage (b (Target F)))) = 'NoBarbie -- break recursion GClassifyBarbie (K1 _i _c) = 'NoBarbie type ClassifyBarbie b = GClassifyBarbie (RecRep (b (Target F)))