{-# LANGUAGE CPP #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE UndecidableInstances #-}
module Bound.ScopeH (
ScopeH (..),
abstractH, abstract1H, abstractHEither,
abstractHName, abstract1HName,
instantiateH, instantiate1H, instantiateHEither,
fromScopeH,
toScopeH,
lowerScopeH,
convertFromScope,
splatH,
bindingsH,
mapBoundH,
mapScopeH,
foldMapBoundH,
foldMapScopeH,
traverseBoundH_,
traverseScopeH_,
traverseBoundH,
traverseScopeH,
bitraverseScopeH,
bitransverseScopeH,
) where
import Bound (Scope (..), Var (..))
import Bound.Name (Name (..))
import Control.DeepSeq (NFData (..))
import Control.Monad.Module (Module (..))
import Data.Bifoldable (bifoldMap, bitraverse_)
import Data.Bifunctor (bimap)
import Data.Bitraversable (Bitraversable (..))
import Data.Foldable (traverse_)
import Data.Functor.Classes
import Data.Hashable (Hashable (..))
import Data.Hashable.Lifted (Hashable1 (..), hashWithSalt1)
newtype ScopeH b f m a = ScopeH { unscopeH :: f (Var b (m a)) }
instance (Functor f, Monad m) => Module (ScopeH b f m) m where
ScopeH s >>== k = ScopeH $ fmap (fmap (>>= k)) s
instance (Functor f, Functor m) => Functor (ScopeH b f m) where
fmap f (ScopeH a) = ScopeH $ fmap (fmap (fmap f)) a
instance (Foldable f, Foldable m) => Foldable (ScopeH b f m) where
foldMap f (ScopeH a) = foldMap (foldMap (foldMap f)) a
foldr f z (ScopeH a) = foldr (flip (foldr (flip (foldr f)))) z a
instance (Traversable f, Traversable m) => Traversable (ScopeH b f m) where
traverse f (ScopeH a) = ScopeH <$> traverse (traverse (traverse f)) a
instance (Hashable b, Module f m, Hashable1 f, Hashable1 m) => Hashable1 (ScopeH b f m) where
liftHashWithSalt h s m = liftHashWithSalt (liftHashWithSalt h) s (fromScopeH m)
{-# INLINE liftHashWithSalt #-}
instance (Hashable b, Module f m, Hashable1 f, Hashable1 m, Hashable a) => Hashable (ScopeH b f m a) where
hashWithSalt n m = hashWithSalt1 n (fromScopeH m)
{-# INLINE hashWithSalt #-}
instance NFData (f (Var b (m a))) => NFData (ScopeH b f m a) where
rnf scope = rnf (unscopeH scope)
instance (Module f m, Eq b, Eq1 f, Eq1 m, Eq a) => Eq (ScopeH b f m a) where (==) = eq1
instance (Module f m, Ord b, Ord1 f, Ord1 m, Ord a) => Ord (ScopeH b f m a) where compare = compare1
instance (Show b, Show1 f, Show1 m, Show a) => Show (ScopeH b f m a) where showsPrec = showsPrec1
instance (Read b, Read1 f, Read1 m, Read a) => Read (ScopeH b f m a) where readsPrec = readsPrec1
instance (Module f m, Eq b, Eq1 f, Eq1 m) => Eq1 (ScopeH b f m) where
liftEq f m n = liftEq (liftEq f) (fromScopeH m) (fromScopeH n)
instance (Module f m, Ord b, Ord1 f, Ord1 m) => Ord1 (ScopeH b f m) where
liftCompare f m n = liftCompare (liftCompare f) (fromScopeH m) (fromScopeH n)
instance (Show b, Show1 f, Show1 m) => Show1 (ScopeH b f m) where
liftShowsPrec sp sl d (ScopeH x) = showsUnaryWith
(liftShowsPrec (liftShowsPrec sp' sl') (liftShowList sp' sl'))
"ScopeH" d x
where
sp' = liftShowsPrec sp sl
sl' = liftShowList sp sl
instance (Read b, Read1 f, Read1 m) => Read1 (ScopeH b f m) where
liftReadsPrec f g = readsData $ readsUnaryWith
(liftReadsPrec (liftReadsPrec f' g') (liftReadList f' g'))
"ScopeH" ScopeH
where
f' = liftReadsPrec f g
g' = liftReadList f g
abstractH :: (Functor f, Monad m) => (a -> Maybe b) -> f a -> ScopeH b f m a
abstractH f e = ScopeH (fmap k e) where
k y = case f y of
Just z -> B z
Nothing -> F (return y)
{-# INLINE abstractH #-}
abstract1H :: (Functor f, Monad m, Eq a) => a -> f a -> ScopeH () f m a
abstract1H a = abstractH (\b -> if a == b then Just () else Nothing)
{-# INLINE abstract1H #-}
abstractHEither :: (Functor f, Monad m) => (a -> Either b c) -> f a -> ScopeH b f m c
abstractHEither f e = ScopeH (fmap k e) where
k y = case f y of
Left z -> B z
Right y' -> F (return y')
{-# INLINE abstractHEither #-}
abstractHName :: (Functor f, Monad m) => (a -> Maybe b) -> f a -> ScopeH (Name a b) f m a
abstractHName f t = ScopeH (fmap k t) where
k a = case f a of
Just b -> B (Name a b)
Nothing -> F (return a)
{-# INLINE abstractHName #-}
abstract1HName :: (Functor f, Monad m, Eq a) => a -> f a -> ScopeH (Name a ()) f m a
abstract1HName a = abstractHName (\b -> if a == b then Just () else Nothing)
{-# INLINE abstract1HName #-}
instantiateH :: Module f m => (b -> m a) -> ScopeH b f m a -> f a
instantiateH k (ScopeH e) = e >>== \v -> case v of
B b -> k b
F a -> a
{-# INLINE instantiateH #-}
instantiate1H :: Module f m => m a -> ScopeH b f m a -> f a
instantiate1H e = instantiateH (const e)
{-# INLINE instantiate1H #-}
instantiateHEither :: Module f m => (Either b a -> m c) -> ScopeH b f m a -> f c
instantiateHEither f (ScopeH e) = e >>== \v -> case v of
B b -> f (Left b)
F ea -> ea >>= f . Right
{-# INLINE instantiateHEither #-}
fromScopeH :: Module f m => ScopeH b f m a -> f (Var b a)
fromScopeH (ScopeH s) = s >>== \v -> case v of
F e -> fmap F e
B b -> return (B b)
toScopeH :: (Functor f, Monad m) => f (Var b a) -> ScopeH b f m a
toScopeH e = ScopeH (fmap (fmap return) e)
lowerScopeH
:: (Functor f, Functor f)
=> (forall x. f x -> h x)
-> (forall x. m x -> h x)
-> ScopeH b f m a -> Scope b h a
lowerScopeH f m (ScopeH x) = Scope (f (fmap (fmap m) x))
convertFromScope :: Scope b f a -> ScopeH b f f a
convertFromScope (Scope x) = ScopeH x
splatH :: Module f m => (a -> m c) -> (b -> m c) -> ScopeH b f m a -> f c
splatH f unbind (ScopeH e) = e >>== \v -> case v of
B b -> unbind b
F ea -> ea >>= f
{-# INLINE splatH #-}
bindingsH :: Foldable f => ScopeH b f m a -> [b]
bindingsH (ScopeH s) = foldr f [] s where
f (B v) vs = v : vs
f _ vs = vs
{-# INLINE bindingsH #-}
mapBoundH :: Functor f => (b -> b') -> ScopeH b f m a -> ScopeH b' f m a
mapBoundH f (ScopeH s) = ScopeH (fmap f' s) where
f' (B b) = B (f b)
f' (F a) = F a
{-# INLINE mapBoundH #-}
mapScopeH
:: (Functor f, Functor m)
=> (b -> d) -> (a -> c)
-> ScopeH b f m a -> ScopeH d f m c
mapScopeH f g (ScopeH s) = ScopeH $ fmap (bimap f (fmap g)) s
{-# INLINE mapScopeH #-}
foldMapBoundH :: (Foldable f, Monoid r) => (b -> r) -> ScopeH b f m a -> r
foldMapBoundH f (ScopeH s) = foldMap f' s where
f' (B a) = f a
f' _ = mempty
{-# INLINE foldMapBoundH #-}
foldMapScopeH
:: (Foldable f, Foldable m, Monoid r)
=> (b -> r) -> (a -> r)
-> ScopeH b f m a -> r
foldMapScopeH f g (ScopeH s) = foldMap (bifoldMap f (foldMap g)) s
{-# INLINE foldMapScopeH #-}
traverseBoundH_ :: (Applicative g, Foldable f) => (b -> g d) -> ScopeH b f m a -> g ()
traverseBoundH_ f (ScopeH s) = traverse_ f' s where
f' (B a) = () <$ f a
f' _ = pure ()
{-# INLINE traverseBoundH_ #-}
traverseScopeH_
:: (Applicative g, Foldable f, Foldable m)
=> (b -> g d) -> (a -> g c)
-> ScopeH b f m a -> g ()
traverseScopeH_ f g (ScopeH s) = traverse_ (bitraverse_ f (traverse_ g)) s
{-# INLINE traverseScopeH_ #-}
traverseBoundH
:: (Applicative g, Traversable f)
=> (b -> g c) -> ScopeH b f m a -> g (ScopeH c f m a)
traverseBoundH f (ScopeH s) = ScopeH <$> traverse f' s where
f' (B b) = B <$> f b
f' (F a) = pure (F a)
{-# INLINE traverseBoundH #-}
traverseScopeH
:: (Applicative g, Traversable f, Traversable m)
=> (b -> g d) -> (a -> g c)
-> ScopeH b f m a -> g (ScopeH d f m c)
traverseScopeH f g (ScopeH s) = ScopeH <$> traverse (bitraverse f (traverse g)) s
{-# INLINE traverseScopeH #-}
bitraverseScopeH
:: (Applicative g, Bitraversable f, Bitraversable m)
=> (k -> g k')
-> (l -> g l')
-> (a -> g a')
-> ScopeH b (f k) (m l) a
-> g (ScopeH b (f k') (m l') a')
bitraverseScopeH k l = bitransverseScopeH (bitraverse k) (bitraverse l)
{-# INLINE bitraverseScopeH #-}
bitransverseScopeH
:: Applicative g
=> (forall x x'. (x -> g x') -> f x -> g (f' x'))
-> (forall x x'. (x -> g x') -> m x -> g (m' x'))
-> (a -> g a')
-> ScopeH b f m a
-> g (ScopeH b f' m' a')
bitransverseScopeH tauF tauM f = fmap ScopeH . tauF (traverse (tauM f)) . unscopeH
{-# INLINE bitransverseScopeH #-}