{-# LANGUAGE PatternSynonyms                 #-}
{-# LANGUAGE ViewPatterns                 #-}
{-# LANGUAGE LambdaCase            #-}
module Control.Monad.Foil.TH.Util where

import Language.Haskell.TH

peelConT :: Type -> Maybe (Name, [Type])
peelConT :: Type -> Maybe (Name, [Type])
peelConT (ConT Name
name) = (Name, [Type]) -> Maybe (Name, [Type])
forall a. a -> Maybe a
Just (Name
name, [])
peelConT (AppT Type
f Type
x) =
  case Type -> Maybe (Name, [Type])
peelConT Type
f of
    Just (Name
g, [Type]
xs) -> (Name, [Type]) -> Maybe (Name, [Type])
forall a. a -> Maybe a
Just (Name
g, [Type]
xs [Type] -> [Type] -> [Type]
forall a. [a] -> [a] -> [a]
++ [Type
x])
    Maybe (Name, [Type])
Nothing -> Maybe (Name, [Type])
forall a. Maybe a
Nothing
peelConT Type
_ = Maybe (Name, [Type])
forall a. Maybe a
Nothing

unpeelConT :: Name -> [Type] -> Type
unpeelConT :: Name -> [Type] -> Type
unpeelConT = (Type -> Type -> Type) -> Type -> [Type] -> Type
forall b a. (b -> a -> b) -> b -> [a] -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl Type -> Type -> Type
AppT (Type -> [Type] -> Type)
-> (Name -> Type) -> Name -> [Type] -> Type
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Name -> Type
ConT

pattern PeelConT :: Name -> [Type] -> Type
pattern $mPeelConT :: forall {r}. Type -> (Name -> [Type] -> r) -> ((# #) -> r) -> r
$bPeelConT :: Name -> [Type] -> Type
PeelConT name types <- (peelConT -> Just (name, types)) where
  PeelConT Name
name [Type]
types = Name -> [Type] -> Type
unpeelConT Name
name [Type]
types

tvarName :: TyVarBndr a -> Name
tvarName :: forall a. TyVarBndr a -> Name
tvarName = \case
  PlainTV Name
name a
_ -> Name
name
  KindedTV Name
name a
_ Type
_ -> Name
name

removeName :: VarBangType -> BangType
removeName :: VarBangType -> BangType
removeName (Name
_name, Bang
bang_, Type
type_) = (Bang
bang_, Type
type_)