{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE NoMonomorphismRestriction #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE TypeOperators #-}
module Language.Expression.Scope where
import Control.Lens
import Language.Expression
class HBound k where
(^>>>=) :: (HMonad h) => k h t a -> (forall b. t b -> h t' b) -> k h t' a
data BV g f a where
B :: g a -> BV g f a
F :: f a -> BV g f a
instance HFunctor (BV g) where
hmap = hliftM
instance HPointed (BV g) where
hpure = F
instance HBind (BV g) where
B x ^>>= _ = B x
F x ^>>= f = f x
instance HMonad (BV g)
instance HTraversable (BV g) where
htraverse = hbitraverseBV pure
foldBV :: (w a -> r) -> (v a -> r) -> BV w v a -> r
foldBV f g = \case
B x -> f x
F y -> g y
instance HBifunctor BV where
hbimap = hbimapBV
instance HBitraversable BV where
hbitraverse = hbitraverseBV
hbitraverseBV :: (Functor t) => (g a -> t (g' b)) -> (f a -> t (f' b)) -> BV g f a -> t (BV g' f' b)
hbitraverseBV f g = foldBV (fmap B . f) (fmap F . g)
hbimapBV :: (g a -> g' b) -> (f a -> f' b) -> BV g f a -> BV g' f' b
hbimapBV f g = foldBV (B . f) (F . g)
instance HBifoldableAt k BV where
hbifoldMap = foldBV
newtype Scope g h f a = Scope { unscope :: h (BV g (h f)) a }
_Scope :: Iso (Scope g h f a) (Scope g' h' f' a') (h (BV g (h f)) a) (h' (BV g' (h' f')) a')
_Scope = iso unscope Scope
instance HFunctor h => HFunctor (Scope g h) where
hmap f = from _Scoped %~ hfirst f
instance HPointed h => HPointed (Scope g h) where
hpure = Scope . hpure . hpure . hpure
instance HTraversable h => HTraversable (Scope g h) where
htraverse f = _Scope %%~ htraverse (htraverse (htraverse f))
instance HDuofunctor (Scope g) where
hduomap g f = _Scope %~ g (hmap (g f))
instance HDuotraversable (Scope g) where
hduotraverse g f = _Scope %%~ g (htraverse (g f))
instance HBound (Scope g) where
Scope x ^>>>= f = Scope (x ^>>= foldBV (hpure . B) (hmap (F . f)))
hbitraverseScope
:: (Applicative t, HTraversable h)
=> (forall b. g b -> t (g' b))
-> (forall b. f b -> t (f' b))
-> Scope g h f a
-> t (Scope g' h f' a)
hbitraverseScope g f = from _Scoped %%~ hbitraverse f g
freeVar :: (HPointed h) => f a -> Scope g h f a
freeVar = Scope . hpure . hpure . hpure
boundVar :: (HPointed h) => g a -> Scope g h f a
boundVar = Scope . hpure . B
liftScope :: (HFunctor h, HPointed h) => h f a -> Scope g h f a
liftScope = Scope . hmap (hpure . hpure)
abstractTraverse :: (HMonad h, HTraversable h, Applicative t) => (forall b. f b -> t (Maybe (g b))) -> h f a -> t (Scope g h f a)
abstractTraverse f = fmap Scope . htraverse (\y -> maybe ((hpure . hpure) y) B <$> f y)
abstract :: (HMonad h) => (forall b. f b -> Maybe (g b)) -> h f a -> Scope g h f a
abstract f = Scope . hmap (\y -> maybe ((hpure . hpure) y) B $ f y)
newtype Scoped h f g a = Scoped { unscoped :: Scope g h f a }
_Scoped :: Iso (Scoped h f g a) (Scoped h' f' g' a') (Scope g h f a) (Scope g' h' f' a')
_Scoped = iso unscoped Scoped
instance HFunctor h => HFunctor (Scoped h f) where
hmap = hsecond
instance HFunctor h => HBifunctor (Scoped h) where
hbimap f g = _Scoped . _Scope %~ hmap (hbimap g (hmap f))
instance HTraversable h => HBitraversable (Scoped h) where
hbitraverse f g = _Scoped . _Scope %%~ htraverse (hbitraverse g (htraverse f))
instance HTraversable h => HTraversable (Scoped h f) where
htraverse = hbitraverse pure
data SFree h f a
= SPure (f a)
| SWrap (h (Scoped (SFree h) f) (SFree h f) a)
instance HDuofunctor h => HFunctor (SFree h) where
hmap = hliftM
instance HPointed (SFree h) where
hpure = SPure
instance HDuofunctor h => HBind (SFree h) where
SPure x ^>>= f = f x
SWrap x ^>>= f = SWrap (hduomap (\g -> (\(Scoped y) -> Scoped (y ^>>>= f)) . hmap g) (^>>= f) x)
instance HDuofunctor h => HMonad (SFree h)
instance (HDuotraversable h) => HTraversable (SFree h) where
htraverse f = \case
SPure x -> SPure <$> f x
SWrap x -> SWrap <$> hduotraverse (hbitraverse f) (htraverse f) x
instance HDuofoldableAt k (Scope k) where
hduofoldMap f g = f (hbifoldMap id (f g)) . view _Scope
instance (HFunctor h, HFoldableAt k h) => HBifoldableAt k (Scoped h) where
hbifoldMap f g = hfoldMap (hbifoldMap g (hfoldMap f)) . view (_Scoped . _Scope)
instance (HDuotraversable h, HDuofoldableAt k h) => HFoldableAt k (SFree h) where
hfoldMap f = \case
SPure x -> f x
SWrap x ->
hduofoldMap
(\g -> hduofoldMap hfoldMap f . view _Scoped . hsecond g)
(hfoldMap f)
x