content: {-# LANGUAGE UndecidableInstances #-}
  
  module GHC.TypeLits.Extra.Symbol (
    StripPrefix,
    ToLower,
  ) where
  
  import GHC.TypeLits (ConsSymbol, Symbol, UnconsSymbol)
  
  -- | Strip `prefix` from `symbol`. Return `symbol` as-is if the prefix doesn't match.
  type family StripPrefix (prefix :: Symbol) (symbol :: Symbol) :: Symbol where
    StripPrefix prefix symbol =
      FromMaybe
        symbol
        (StripPrefix' (UnconsSymbol prefix) (UnconsSymbol symbol))
  
  -- | Strip `prefix` from `symbol`. Return Nothing if the prefix doesn't match.
  type family StripPrefix' (prefix :: Maybe (Char, Symbol)) (symbol :: Maybe (Char, Symbol)) :: Maybe Symbol where
    StripPrefix' 'Nothing 'Nothing = 'Just ""
    StripPrefix' 'Nothing ('Just '(x, xs)) = 'Just (ConsSymbol x xs)
    StripPrefix' _p 'Nothing = 'Nothing
    StripPrefix' ('Just '(p, ps)) ('Just '(p, ss)) = StripPrefix' (UnconsSymbol ps) (UnconsSymbol ss)
    StripPrefix' ('Just '(p, ps)) ('Just '(_, ss)) = 'Nothing
  
  type family ToLower (sym :: Symbol) :: Symbol where
    ToLower sym = ToLower' (UnconsSymbol sym)
  
  type family ToLower' (pair :: Maybe (Char, Symbol)) :: Symbol where
    ToLower' 'Nothing = ""
    ToLower' ('Just '(c, cs)) = ConsSymbol (ToLowerC c) (ToLower' (UnconsSymbol cs))
  
  type family ToLowerC (c :: Char) :: Char where
    ToLowerC 'A' = 'a'
    ToLowerC 'B' = 'b'
    ToLowerC 'C' = 'c'
    ToLowerC 'D' = 'd'
    ToLowerC 'E' = 'e'
    ToLowerC 'F' = 'f'
    ToLowerC 'G' = 'g'
    ToLowerC 'H' = 'h'
    ToLowerC 'I' = 'i'
    ToLowerC 'J' = 'j'
    ToLowerC 'K' = 'k'
    ToLowerC 'L' = 'l'
    ToLowerC 'M' = 'm'
    ToLowerC 'N' = 'n'
    ToLowerC 'O' = 'o'
    ToLowerC 'P' = 'p'
    ToLowerC 'Q' = 'q'
    ToLowerC 'R' = 'r'
    ToLowerC 'S' = 's'
    ToLowerC 'T' = 't'
    ToLowerC 'U' = 'u'
    ToLowerC 'V' = 'v'
    ToLowerC 'W' = 'w'
    ToLowerC 'X' = 'x'
    ToLowerC 'Y' = 'y'
    ToLowerC 'Z' = 'z'
    ToLowerC a = a
  
  type family FromMaybe (def :: a) (maybe :: Maybe a) :: a where
    FromMaybe def 'Nothing = def
    FromMaybe def ('Just a) = a
  