{-# LANGUAGE UndecidableInstances #-}
module Generic.Type.CstrPath
( type GCstrPath
, GCstrChoice(..)
) where
import GHC.Generics
import GHC.TypeLits
import Data.Type.Bool ( type If )
import Data.Type.Equality ( type (==) )
import Data.Kind ( type Type )
data GCstrChoice = GoL1
| GoR1
type GCstrPath :: Symbol -> (k -> Type) -> Either ErrorMessage [GCstrChoice]
type family GCstrPath name gf where
GCstrPath name V1 = Left (Text "type is empty (no constructors)")
GCstrPath name gf = GCstrPath' name '[ '( '[], gf)]
type family GCstrPath' name zippers where
GCstrPath' name ('(bcs, (l :+: r)) : zippers) =
GCstrPath' name ('((GoL1 : bcs), l) : '((GoR1 : bcs), r) : zippers)
GCstrPath' name ('(bcs, (C1 (MetaCons name' _ _) _)) : zippers) =
If (name == name') (Right (Reverse bcs)) (GCstrPath' name zippers)
GCstrPath' name '[] = Left (Text "no matching constructor")
type Reverse as = Reverse' as '[]
type family Reverse' (as :: [k]) (acc :: [k]) :: [k] where
Reverse' '[] acc = acc
Reverse' (a : as) acc = Reverse' as (a : acc)