hypertypes-0.2.2: test/Hyper/Syntax/NamelessScope/InvDeBruijn.hs
module Hyper.Syntax.NamelessScope.InvDeBruijn
( InvDeBruijnIndex (..)
, inverseDeBruijnIndex
, scope
, scopeVar
) where
import Control.Lens (Prism', iso)
import Control.Lens.Operators
import Data.Proxy (Proxy (..))
import Hyper.Syntax.NamelessScope (DeBruijnIndex (..), EmptyScope, Scope (..), ScopeVar (..))
import Hyper.Type (type (#))
import Prelude
class DeBruijnIndex a => InvDeBruijnIndex a where
deBruijnIndexMax :: Proxy a -> Int
instance InvDeBruijnIndex EmptyScope where
deBruijnIndexMax _ = -1
instance InvDeBruijnIndex a => InvDeBruijnIndex (Maybe a) where
deBruijnIndexMax _ = 1 + deBruijnIndexMax (Proxy @a)
inverseDeBruijnIndex :: forall a. InvDeBruijnIndex a => Prism' Int a
inverseDeBruijnIndex =
iso (l -) (l -) . deBruijnIndex
where
l = deBruijnIndexMax (Proxy @a)
scope ::
forall expr a f.
InvDeBruijnIndex a =>
(Int -> f # expr (Maybe a)) ->
Scope expr a # f
scope f = Scope (f (inverseDeBruijnIndex # (Nothing :: Maybe a)))
scopeVar :: InvDeBruijnIndex a => Int -> ScopeVar expr a f
scopeVar x = ScopeVar (x ^?! inverseDeBruijnIndex)