packages feed

hobbits 1.2.4 → 1.3

raw patch · 36 files changed

+2915/−2225 lines, 36 filesdep +containersdep +vectordep ~haskell-src-extsdep ~template-haskellPVP ok

version bump matches the API change (PVP)

Dependencies added: containers, vector

Dependency ranges changed: haskell-src-exts, template-haskell

API changes (from Hackage documentation)

- Data.Binding.Hobbits.Examples.LambdaLifting.Terms: instance Data.Binding.Hobbits.NuMatching.NuMatching (Data.Binding.Hobbits.Examples.LambdaLifting.Terms.DTerm a0)
- Data.Binding.Hobbits.Examples.LambdaLifting.Terms: instance Data.Binding.Hobbits.NuMatching.NuMatching (Data.Binding.Hobbits.Examples.LambdaLifting.Terms.Decl a0)
- Data.Binding.Hobbits.Examples.LambdaLifting.Terms: instance Data.Binding.Hobbits.NuMatching.NuMatching (Data.Binding.Hobbits.Examples.LambdaLifting.Terms.Decls a0)
- Data.Binding.Hobbits.Examples.LambdaLifting.Terms: instance Data.Binding.Hobbits.NuMatching.NuMatching (Data.Binding.Hobbits.Examples.LambdaLifting.Terms.Term a0)
- Data.Binding.Hobbits.Liftable: instance Data.Binding.Hobbits.Liftable.Liftable (Data.Type.RList.Member c a)
- Data.Binding.Hobbits.Liftable: instance Data.Binding.Hobbits.Liftable.Liftable a => Data.Binding.Hobbits.Liftable.Liftable (GHC.Base.Maybe a)
- Data.Binding.Hobbits.Mb: instance Data.Type.RList.TypeCtx ctx => GHC.Base.Applicative (Data.Binding.Hobbits.Internal.Mb.Mb ctx)
- Data.Binding.Hobbits.Mb: instance GHC.Base.Functor (Data.Binding.Hobbits.Internal.Mb.Mb ctx)
- Data.Binding.Hobbits.Mb: instance GHC.Show.Show a => GHC.Show.Show (Data.Binding.Hobbits.Internal.Mb.Mb c a)
- Data.Binding.Hobbits.NuMatching: NuMatchingObj :: () -> NuMatchingObj a
- Data.Binding.Hobbits.NuMatching: class NuMatching1 f
- Data.Binding.Hobbits.NuMatching: class NuMatchingList args
- Data.Binding.Hobbits.NuMatching: data NuMatchingObj a
- Data.Binding.Hobbits.NuMatching: instance (Data.Binding.Hobbits.NuMatching.NuMatching a, Data.Binding.Hobbits.NuMatching.NuMatching b) => Data.Binding.Hobbits.NuMatching.NuMatching (Data.Either.Either a b)
- Data.Binding.Hobbits.NuMatching: instance (Data.Binding.Hobbits.NuMatching.NuMatching1 f, Data.Binding.Hobbits.NuMatching.NuMatchingList ctx) => Data.Binding.Hobbits.NuMatching.NuMatching (Data.Type.RList.MapRList f ctx)
- Data.Binding.Hobbits.NuMatching: instance (Data.Binding.Hobbits.NuMatching.NuMatchingList args, Data.Binding.Hobbits.NuMatching.NuMatching a) => Data.Binding.Hobbits.NuMatching.NuMatchingList (args 'Data.Type.RList.:> a)
- Data.Binding.Hobbits.NuMatching: instance Data.Binding.Hobbits.NuMatching.NuMatching (Data.Binding.Hobbits.Internal.Name.Name a)
- Data.Binding.Hobbits.NuMatching: instance Data.Binding.Hobbits.NuMatching.NuMatching (Data.Type.RList.Member c a)
- Data.Binding.Hobbits.NuMatching: instance Data.Binding.Hobbits.NuMatching.NuMatching a => Data.Binding.Hobbits.NuMatching.NuMatching (Data.Binding.Hobbits.Internal.Mb.Mb ctx a)
- Data.Binding.Hobbits.NuMatching: instance Data.Binding.Hobbits.NuMatching.NuMatching a => Data.Binding.Hobbits.NuMatching.NuMatching (GHC.Base.Maybe a)
- Data.Binding.Hobbits.NuMatching: instance Data.Binding.Hobbits.NuMatching.NuMatchingList 'Data.Type.RList.RNil
- Data.Binding.Hobbits.NuMatching: nuMatchingListProof :: NuMatchingList args => MapRList NuMatchingObj args
- Data.Binding.Hobbits.NuMatching: nuMatchingProof1 :: (NuMatching1 f, NuMatching a) => NuMatchingObj (f a)
- Data.Type.RList: appendMapRList :: MapRList f c1 -> MapRList f c2 -> MapRList f (c1 :++: c2)
- Data.Type.RList: data MapRList f c
- Data.Type.RList: instance Data.Type.RList.TypeCtx ctx => Data.Type.RList.TypeCtx (ctx 'Data.Type.RList.:> a)
- Data.Type.RList: instance GHC.Show.Show (Data.Type.RList.Member r a)
- Data.Type.RList: mapMapRList :: (forall x. f x -> g x) -> MapRList f c -> MapRList g c
- Data.Type.RList: mapMapRList2 :: (forall x. f x -> g x -> h x) -> MapRList f c -> MapRList g c -> MapRList h c
- Data.Type.RList: mapRListLookup :: Member c a -> MapRList f c -> f a
- Data.Type.RList: mapRListToList :: MapRList (Constant a) c -> [a]
- Data.Type.RList: membersEq :: Member ctx a -> Member ctx b -> Maybe (a :~: b)
- Data.Type.RList: proxyCons :: Proxy r -> f a -> Proxy (r :> a)
- Data.Type.RList: showsPrecMember :: Bool -> Member ctx a -> ShowS
- Data.Type.RList: splitMapRList :: (c ~ (c1 :++: c2)) => Proxy c1 -> MapRList any c2 -> MapRList f c -> (MapRList f c1, MapRList f c2)
+ Data.Binding.Hobbits: (:>) :: RList a -> a -> RList a
+ Data.Binding.Hobbits: RNil :: RList a
+ Data.Binding.Hobbits: [:>:] :: RAssign f c -> f a -> RAssign f (c :> a)
+ Data.Binding.Hobbits: [Append_Base] :: Append ctx RNil ctx
+ Data.Binding.Hobbits: [Append_Step] :: Append ctx1 ctx2 ctx -> Append ctx1 (ctx2 :> a) (ctx :> a)
+ Data.Binding.Hobbits: [MNil] :: RAssign f RNil
+ Data.Binding.Hobbits: [Member_Base] :: Member (ctx :> a) a
+ Data.Binding.Hobbits: [Member_Step] :: Member ctx a -> Member (ctx :> b) a
+ Data.Binding.Hobbits: data Append ctx1 ctx2 ctx
+ Data.Binding.Hobbits: data Member (ctx :: RList k1) (a :: k2)
+ Data.Binding.Hobbits: data RAssign (f :: k -> *) (c :: RList k)
+ Data.Binding.Hobbits: data RList a
+ Data.Binding.Hobbits: infixr 5 :++:
+ Data.Binding.Hobbits: type family (r1 :: RList k) :++: (r2 :: RList k) :: RList k
+ Data.Binding.Hobbits.Closed: instance Data.Binding.Hobbits.Closed.Closable (Data.Binding.Hobbits.Internal.Closed.Closed a)
+ Data.Binding.Hobbits.Closed: instance Data.Binding.Hobbits.Closed.Closable GHC.Integer.Type.Integer
+ Data.Binding.Hobbits.Closed: instance Data.Binding.Hobbits.Closed.Closable GHC.Types.Bool
+ Data.Binding.Hobbits.Closed: instance Data.Binding.Hobbits.Closed.Closable GHC.Types.Char
+ Data.Binding.Hobbits.Closed: instance Data.Binding.Hobbits.Closed.Closable GHC.Types.Int
+ Data.Binding.Hobbits.Closed: instance Data.Binding.Hobbits.Closed.Closable a => Data.Binding.Hobbits.Closed.Closable [a]
+ Data.Binding.Hobbits.Closed: instance Data.Binding.Hobbits.Closed.ClosableAny1 Data.Proxy.Proxy
+ Data.Binding.Hobbits.Closed: instance forall k (a :: k). Data.Binding.Hobbits.Closed.Closable (Data.Proxy.Proxy a)
+ Data.Binding.Hobbits.Closed: instance forall k (f :: k -> *) (ctx :: Data.Type.RList.RList k). Data.Binding.Hobbits.Closed.ClosableAny1 f => Data.Binding.Hobbits.Closed.Closable (Data.Type.RList.RAssign f ctx)
+ Data.Binding.Hobbits.Closed: instance forall k k1 (ctx :: Data.Type.RList.RList k1). Data.Binding.Hobbits.Closed.ClosableAny1 (Data.Type.RList.Member ctx)
+ Data.Binding.Hobbits.Closed: instance forall k2 k1 (ctx :: Data.Type.RList.RList k1) (a :: k2). Data.Binding.Hobbits.Closed.Closable (Data.Type.RList.Member ctx a)
+ Data.Binding.Hobbits.Closed: unsafeClose :: a -> Closed a
+ Data.Binding.Hobbits.Examples.LambdaLifting.Terms: instance Data.Binding.Hobbits.NuMatching.NuMatching (Data.Binding.Hobbits.Examples.LambdaLifting.Terms.DTerm a)
+ Data.Binding.Hobbits.Examples.LambdaLifting.Terms: instance Data.Binding.Hobbits.NuMatching.NuMatching (Data.Binding.Hobbits.Examples.LambdaLifting.Terms.Decl a)
+ Data.Binding.Hobbits.Examples.LambdaLifting.Terms: instance Data.Binding.Hobbits.NuMatching.NuMatching (Data.Binding.Hobbits.Examples.LambdaLifting.Terms.Decls a)
+ Data.Binding.Hobbits.Examples.LambdaLifting.Terms: instance Data.Binding.Hobbits.NuMatching.NuMatching (Data.Binding.Hobbits.Examples.LambdaLifting.Terms.Term a)
+ Data.Binding.Hobbits.Liftable: instance Data.Binding.Hobbits.Liftable.Liftable GHC.Natural.Natural
+ Data.Binding.Hobbits.Liftable: instance Data.Binding.Hobbits.Liftable.Liftable a => Data.Binding.Hobbits.Liftable.Liftable (GHC.Maybe.Maybe a)
+ Data.Binding.Hobbits.Liftable: instance forall k (a :: k) (b :: k). Data.Binding.Hobbits.Liftable.Liftable (a Data.Type.Equality.:~: b)
+ Data.Binding.Hobbits.Liftable: instance forall k (a :: k). Data.Binding.Hobbits.Liftable.Liftable (Data.Proxy.Proxy a)
+ Data.Binding.Hobbits.Liftable: instance forall k a (ctx :: Data.Type.RList.RList k). GHC.Classes.Eq a => GHC.Classes.Eq (Data.Binding.Hobbits.Internal.Mb.Mb ctx a)
+ Data.Binding.Hobbits.Liftable: instance forall k2 k1 (c :: Data.Type.RList.RList k1) (a :: k2). Data.Binding.Hobbits.Liftable.Liftable (Data.Type.RList.Member c a)
+ Data.Binding.Hobbits.Mb: extMb :: Mb ctx a -> Mb (ctx :> tp) a
+ Data.Binding.Hobbits.Mb: extMbMulti :: RAssign f ctx2 -> Mb ctx1 a -> Mb (ctx1 :++: ctx2) a
+ Data.Binding.Hobbits.Mb: hcmpName :: forall (a :: k1) (b :: k2). Name a -> Name b -> Maybe (a :~~: b)
+ Data.Binding.Hobbits.Mb: instance forall k (ctx :: Data.Type.RList.RList k). Data.Type.RList.TypeCtx ctx => GHC.Base.Applicative (Data.Binding.Hobbits.Internal.Mb.Mb ctx)
+ Data.Binding.Hobbits.Mb: instance forall k (ctx :: Data.Type.RList.RList k). GHC.Base.Functor (Data.Binding.Hobbits.Internal.Mb.Mb ctx)
+ Data.Binding.Hobbits.Mb: instance forall k a (c :: Data.Type.RList.RList k). GHC.Show.Show a => GHC.Show.Show (Data.Binding.Hobbits.Internal.Mb.Mb c a)
+ Data.Binding.Hobbits.Mb: mbMap2 :: (a -> b -> c) -> Mb ctx a -> Mb ctx b -> Mb ctx c
+ Data.Binding.Hobbits.Mb: mbPure :: RAssign f ctx -> a -> Mb ctx a
+ Data.Binding.Hobbits.MonadBind: class Monad m => MonadBind m
+ Data.Binding.Hobbits.MonadBind: class MonadBind m => MonadStrongBind m
+ Data.Binding.Hobbits.MonadBind: instance (Data.Binding.Hobbits.MonadBind.MonadBind m, Data.Binding.Hobbits.MonadBind.BindState s) => Data.Binding.Hobbits.MonadBind.MonadBind (Control.Monad.Trans.State.Lazy.StateT s m)
+ Data.Binding.Hobbits.MonadBind: instance (Data.Binding.Hobbits.MonadBind.MonadClosed m, Data.Binding.Hobbits.Closed.Closable s) => Data.Binding.Hobbits.MonadBind.MonadClosed (Control.Monad.Trans.State.Lazy.StateT s m)
+ Data.Binding.Hobbits.MonadBind: instance (Data.Binding.Hobbits.MonadBind.MonadStrongBind m, Data.Binding.Hobbits.MonadBind.BindState s) => Data.Binding.Hobbits.MonadBind.MonadStrongBind (Control.Monad.Trans.State.Lazy.StateT s m)
+ Data.Binding.Hobbits.MonadBind: instance Data.Binding.Hobbits.MonadBind.BindState (Data.Binding.Hobbits.Internal.Closed.Closed s)
+ Data.Binding.Hobbits.MonadBind: instance Data.Binding.Hobbits.MonadBind.MonadBind Data.Functor.Identity.Identity
+ Data.Binding.Hobbits.MonadBind: instance Data.Binding.Hobbits.MonadBind.MonadBind GHC.Maybe.Maybe
+ Data.Binding.Hobbits.MonadBind: instance Data.Binding.Hobbits.MonadBind.MonadBind m => Data.Binding.Hobbits.MonadBind.MonadBind (Control.Monad.Trans.Reader.ReaderT r m)
+ Data.Binding.Hobbits.MonadBind: instance Data.Binding.Hobbits.MonadBind.MonadClosed Data.Functor.Identity.Identity
+ Data.Binding.Hobbits.MonadBind: instance Data.Binding.Hobbits.MonadBind.MonadStrongBind Data.Functor.Identity.Identity
+ Data.Binding.Hobbits.MonadBind: instance Data.Binding.Hobbits.MonadBind.MonadStrongBind m => Data.Binding.Hobbits.MonadBind.MonadStrongBind (Control.Monad.Trans.Reader.ReaderT r m)
+ Data.Binding.Hobbits.MonadBind: mbM :: (MonadBind m, NuMatching a) => Mb ctx (m a) -> m (Mb ctx a)
+ Data.Binding.Hobbits.MonadBind: strongMbM :: MonadStrongBind m => Mb ctx (m a) -> m (Mb ctx a)
+ Data.Binding.Hobbits.NameMap: (!) :: NameMap f -> Name a -> f a
+ Data.Binding.Hobbits.NameMap: (\\) :: NameMap f -> NameMap f -> NameMap f
+ Data.Binding.Hobbits.NameMap: [NameAndElem] :: Name a -> f a -> NameAndElem f
+ Data.Binding.Hobbits.NameMap: adjust :: (f a -> f a) -> Name a -> NameMap f -> NameMap f
+ Data.Binding.Hobbits.NameMap: alter :: (Maybe (f a) -> Maybe (f a)) -> Name a -> NameMap f -> NameMap f
+ Data.Binding.Hobbits.NameMap: assocs :: NameMap f -> [NameAndElem f]
+ Data.Binding.Hobbits.NameMap: data NameAndElem f
+ Data.Binding.Hobbits.NameMap: data NameMap (f :: k -> *)
+ Data.Binding.Hobbits.NameMap: delete :: Name a -> NameMap f -> NameMap f
+ Data.Binding.Hobbits.NameMap: difference :: NameMap f -> NameMap f -> NameMap f
+ Data.Binding.Hobbits.NameMap: empty :: NameMap f
+ Data.Binding.Hobbits.NameMap: foldl :: (forall b. a -> f b -> a) -> a -> NameMap f -> a
+ Data.Binding.Hobbits.NameMap: foldr :: (forall a. f a -> b -> b) -> b -> NameMap f -> b
+ Data.Binding.Hobbits.NameMap: fromList :: [NameAndElem f] -> NameMap f
+ Data.Binding.Hobbits.NameMap: insert :: Name a -> f a -> NameMap f -> NameMap f
+ Data.Binding.Hobbits.NameMap: instance forall k (f :: k -> *). Data.Binding.Hobbits.NuMatching.NuMatchingAny1 f => Data.Binding.Hobbits.NuMatching.NuMatching (Data.Binding.Hobbits.NameMap.NameAndElem f)
+ Data.Binding.Hobbits.NameMap: intersection :: NameMap f -> NameMap f -> NameMap f
+ Data.Binding.Hobbits.NameMap: liftNameMap :: forall ctx f a. NuMatchingAny1 f => (forall a. Mb ctx (f a) -> Maybe (f a)) -> Mb ctx (NameMap f) -> NameMap f
+ Data.Binding.Hobbits.NameMap: lookup :: Name a -> NameMap f -> Maybe (f a)
+ Data.Binding.Hobbits.NameMap: map :: (forall a. f a -> g a) -> NameMap f -> NameMap g
+ Data.Binding.Hobbits.NameMap: member :: Name a -> NameMap f -> Bool
+ Data.Binding.Hobbits.NameMap: null :: NameMap f -> Bool
+ Data.Binding.Hobbits.NameMap: singleton :: Name a -> f a -> NameMap f
+ Data.Binding.Hobbits.NameMap: size :: NameMap f -> Int
+ Data.Binding.Hobbits.NameMap: union :: NameMap f -> NameMap f -> NameMap f
+ Data.Binding.Hobbits.NameMap: update :: (f a -> Maybe (f a)) -> Name a -> NameMap f -> NameMap f
+ Data.Binding.Hobbits.NameSet: (\\) :: NameSet k -> NameSet k -> NameSet k
+ Data.Binding.Hobbits.NameSet: SomeName :: Name a -> SomeName k
+ Data.Binding.Hobbits.NameSet: data NameSet k
+ Data.Binding.Hobbits.NameSet: data SomeName k
+ Data.Binding.Hobbits.NameSet: delete :: Name (a :: k) -> NameSet k -> NameSet k
+ Data.Binding.Hobbits.NameSet: difference :: NameSet k -> NameSet k -> NameSet k
+ Data.Binding.Hobbits.NameSet: empty :: NameSet k
+ Data.Binding.Hobbits.NameSet: foldl :: (forall (a :: k). r -> Name a -> r) -> r -> NameSet k -> r
+ Data.Binding.Hobbits.NameSet: foldr :: (forall (a :: k). Name a -> r -> r) -> r -> NameSet k -> r
+ Data.Binding.Hobbits.NameSet: fromList :: [SomeName k] -> NameSet k
+ Data.Binding.Hobbits.NameSet: insert :: Name (a :: k) -> NameSet k -> NameSet k
+ Data.Binding.Hobbits.NameSet: instance Data.Binding.Hobbits.NuMatching.NuMatching (Data.Binding.Hobbits.NameSet.SomeName k)
+ Data.Binding.Hobbits.NameSet: intersection :: NameSet k -> NameSet k -> NameSet k
+ Data.Binding.Hobbits.NameSet: liftNameSet :: Mb ctx (NameSet (k :: Type)) -> NameSet k
+ Data.Binding.Hobbits.NameSet: map :: (forall (a :: k). Name a -> Name a) -> NameSet k -> NameSet k
+ Data.Binding.Hobbits.NameSet: member :: Name (a :: k) -> NameSet k -> Bool
+ Data.Binding.Hobbits.NameSet: null :: NameSet k -> Bool
+ Data.Binding.Hobbits.NameSet: singleton :: Name (a :: k) -> NameSet k
+ Data.Binding.Hobbits.NameSet: size :: NameSet k -> Int
+ Data.Binding.Hobbits.NameSet: toList :: NameSet k -> [SomeName k]
+ Data.Binding.Hobbits.NameSet: union :: NameSet k -> NameSet k -> NameSet k
+ Data.Binding.Hobbits.NameSet: unions :: Foldable f => f (NameSet k) -> NameSet k
+ Data.Binding.Hobbits.NuMatching: class NuMatchingAny1 (f :: k -> Type)
+ Data.Binding.Hobbits.NuMatching: instance Data.Binding.Hobbits.NuMatching.NuMatching GHC.Natural.Natural
+ Data.Binding.Hobbits.NuMatching: instance Data.Binding.Hobbits.NuMatching.NuMatching GHC.Types.Double
+ Data.Binding.Hobbits.NuMatching: instance Data.Binding.Hobbits.NuMatching.NuMatching GHC.Types.Float
+ Data.Binding.Hobbits.NuMatching: instance Data.Binding.Hobbits.NuMatching.NuMatching GHC.Types.Word
+ Data.Binding.Hobbits.NuMatching: instance Data.Binding.Hobbits.NuMatching.NuMatching GHC.Word.Word16
+ Data.Binding.Hobbits.NuMatching: instance Data.Binding.Hobbits.NuMatching.NuMatching GHC.Word.Word32
+ Data.Binding.Hobbits.NuMatching: instance Data.Binding.Hobbits.NuMatching.NuMatching GHC.Word.Word64
+ Data.Binding.Hobbits.NuMatching: instance Data.Binding.Hobbits.NuMatching.NuMatching GHC.Word.Word8
+ Data.Binding.Hobbits.NuMatching: instance Data.Binding.Hobbits.NuMatching.NuMatching a => Data.Binding.Hobbits.NuMatching.NuMatching (Data.Vector.Vector a)
+ Data.Binding.Hobbits.NuMatching: instance Data.Binding.Hobbits.NuMatching.NuMatching a => Data.Binding.Hobbits.NuMatching.NuMatchingAny1 (Data.Functor.Constant.Constant a)
+ Data.Binding.Hobbits.NuMatching: instance Data.Binding.Hobbits.NuMatching.NuMatchingAny1 Data.Binding.Hobbits.Internal.Name.Name
+ Data.Binding.Hobbits.NuMatching: instance forall k (a :: k). Data.Binding.Hobbits.NuMatching.NuMatching (Data.Binding.Hobbits.Internal.Name.Name a)
+ Data.Binding.Hobbits.NuMatching: instance forall k (a :: k). Data.Binding.Hobbits.NuMatching.NuMatchingAny1 ((Data.Type.Equality.:~:) a)
+ Data.Binding.Hobbits.NuMatching: instance forall k (f :: k -> *) (a :: k). Data.Binding.Hobbits.NuMatching.NuMatchingAny1 f => Data.Binding.Hobbits.NuMatching.NuMatching (f a)
+ Data.Binding.Hobbits.NuMatching: instance forall k (f :: k -> *) (ctx :: Data.Type.RList.RList k). Data.Binding.Hobbits.NuMatching.NuMatchingAny1 f => Data.Binding.Hobbits.NuMatching.NuMatching (Data.Type.RList.RAssign f ctx)
+ Data.Binding.Hobbits.NuMatching: instance forall k a (ctx :: Data.Type.RList.RList k). Data.Binding.Hobbits.NuMatching.NuMatching a => Data.Binding.Hobbits.NuMatching.NuMatching (Data.Binding.Hobbits.Internal.Mb.Mb ctx a)
+ Data.Binding.Hobbits.NuMatching: nuMatchingAny1Proof :: NuMatchingAny1 f => MbTypeRepr (f a)
+ Data.Binding.Hobbits.NuMatching: unsafeMbTypeRepr :: MbTypeRepr a
+ Data.Binding.Hobbits.NuMatchingInstances: instance (Data.Binding.Hobbits.NuMatching.NuMatching a, Data.Binding.Hobbits.NuMatching.NuMatching b) => Data.Binding.Hobbits.NuMatching.NuMatching (Data.Either.Either a b)
+ Data.Binding.Hobbits.NuMatchingInstances: instance Data.Binding.Hobbits.NuMatching.NuMatching a => Data.Binding.Hobbits.NuMatching.NuMatching (GHC.Maybe.Maybe a)
+ Data.Binding.Hobbits.NuMatchingInstances: instance forall k (a :: k) (b :: k). Data.Binding.Hobbits.NuMatching.NuMatching (a Data.Type.Equality.:~: b)
+ Data.Binding.Hobbits.NuMatchingInstances: instance forall k (a :: k). Data.Binding.Hobbits.NuMatching.NuMatching (Data.Proxy.Proxy a)
+ Data.Binding.Hobbits.NuMatchingInstances: instance forall k a (b :: k). Data.Binding.Hobbits.NuMatching.NuMatching a => Data.Binding.Hobbits.NuMatching.NuMatching (Data.Functor.Constant.Constant a b)
+ Data.Binding.Hobbits.NuMatchingInstances: instance forall k2 k1 (ctx :: Data.Type.RList.RList k1) (a :: k2). Data.Binding.Hobbits.NuMatching.NuMatching (Data.Type.RList.Member ctx a)
+ Data.Type.RList: [HApply] :: forall (f :: k -> Type) (a :: k). f a -> HApply f a
+ Data.Type.RList: append :: RAssign f c1 -> RAssign f c2 -> RAssign f (c1 :++: c2)
+ Data.Type.RList: data HApply (f :: k1 -> Type) (a :: k2)
+ Data.Type.RList: data RAssign (f :: k -> *) (c :: RList k)
+ Data.Type.RList: foldr :: (forall a. f a -> r -> r) -> r -> RAssign f ctx -> r
+ Data.Type.RList: get :: Member c a -> RAssign f c -> f a
+ Data.Type.RList: hget :: forall (f :: k1 -> Type) (c :: RList k1) (a :: k2). Member c a -> RAssign f c -> HApply f a
+ Data.Type.RList: infixr 5 :++:
+ Data.Type.RList: instance forall k (ctx :: Data.Type.RList.RList k) (a :: k). Data.Type.RList.TypeCtx ctx => Data.Type.RList.TypeCtx (ctx 'Data.Type.RList.:> a)
+ Data.Type.RList: instance forall k k1 (ctx :: Data.Type.RList.RList k1). Data.Type.Equality.TestEquality (Data.Type.RList.Member ctx)
+ Data.Type.RList: instance forall k2 k1 (ctx :: Data.Type.RList.RList k1) (a :: k2). GHC.Classes.Eq (Data.Type.RList.Member ctx a)
+ Data.Type.RList: instance forall k2 k1 (r :: Data.Type.RList.RList k1) (a :: k2). GHC.Show.Show (Data.Type.RList.Member r a)
+ Data.Type.RList: map :: (forall x. f x -> g x) -> RAssign f c -> RAssign g c
+ Data.Type.RList: map2 :: (forall x. f x -> g x -> h x) -> RAssign f c -> RAssign g c -> RAssign h c
+ Data.Type.RList: mapRAssign :: (forall x. f x -> g x) -> RAssign f c -> RAssign g c
+ Data.Type.RList: mapToList :: (forall a. f a -> b) -> RAssign f ctx -> [b]
+ Data.Type.RList: memberElem :: TestEquality f => f a -> RAssign f ctx -> Maybe (Member ctx a)
+ Data.Type.RList: modify :: Member c a -> (f a -> f a) -> RAssign f c -> RAssign f c
+ Data.Type.RList: set :: Member c a -> f a -> RAssign f c -> RAssign f c
+ Data.Type.RList: split :: c ~ (c1 :++: c2) => prx c1 -> RAssign any c2 -> RAssign f c -> (RAssign f c1, RAssign f c2)
+ Data.Type.RList: tail :: RAssign f (ctx :> a) -> RAssign f ctx
+ Data.Type.RList: toList :: RAssign (Constant a) c -> [a]
+ Data.Type.RList: type family (r1 :: RList k) :++: (r2 :: RList k) :: RList k
- Data.Binding.Hobbits.Mb: data Mb ctx b
+ Data.Binding.Hobbits.Mb: data Mb (ctx :: RList k) b
- Data.Binding.Hobbits.Mb: data Name a
+ Data.Binding.Hobbits.Mb: data Name (a :: k)
- Data.Binding.Hobbits.Mb: mbCmpName :: Mb c (Name a) -> Mb c (Name b) -> Maybe (a :~: b)
+ Data.Binding.Hobbits.Mb: mbCmpName :: forall (a :: k1) (b :: k1) (c :: RList k2). Mb c (Name a) -> Mb c (Name b) -> Maybe (a :~: b)
- Data.Binding.Hobbits.Mb: mbCombine :: Mb c1 (Mb c2 b) -> Mb (c1 :++: c2) b
+ Data.Binding.Hobbits.Mb: mbCombine :: forall (c1 :: RList k) (c2 :: RList k) a b. Mb c1 (Mb c2 b) -> Mb (c1 :++: c2) b
- Data.Binding.Hobbits.Mb: mbNameBoundP :: Mb ctx (Name a) -> Either (Member ctx a) (Name a)
+ Data.Binding.Hobbits.Mb: mbNameBoundP :: forall (a :: k1) (ctx :: RList k2). Mb ctx (Name a) -> Either (Member ctx a) (Name a)
- Data.Binding.Hobbits.Mb: mbSeparate :: MapRList any ctx2 -> Mb (ctx1 :++: ctx2) a -> Mb ctx1 (Mb ctx2 a)
+ Data.Binding.Hobbits.Mb: mbSeparate :: forall (ctx1 :: RList k) (ctx2 :: RList k) (any :: k -> *) a. RAssign any ctx2 -> Mb (ctx1 :++: ctx2) a -> Mb ctx1 (Mb ctx2 a)
- Data.Binding.Hobbits.Mb: mbToProxy :: Mb ctx a -> MapRList Proxy ctx
+ Data.Binding.Hobbits.Mb: mbToProxy :: forall (ctx :: RList k) (a :: *). Mb ctx a -> RAssign Proxy ctx
- Data.Binding.Hobbits.Mb: nu :: (Name a -> b) -> Binding a b
+ Data.Binding.Hobbits.Mb: nu :: forall (a :: k1) (b :: *). (Name a -> b) -> Binding a b
- Data.Binding.Hobbits.Mb: nuMulti :: MapRList f ctx -> (MapRList Name ctx -> b) -> Mb ctx b
+ Data.Binding.Hobbits.Mb: nuMulti :: RAssign f ctx -> (RAssign Name ctx -> b) -> Mb ctx b
- Data.Binding.Hobbits.Mb: nuMultiWithElim :: TypeCtx ctx => (MapRList Name ctx -> MapRList Identity args -> b) -> MapRList (Mb ctx) args -> Mb ctx b
+ Data.Binding.Hobbits.Mb: nuMultiWithElim :: (RAssign Name ctx -> RAssign Identity args -> b) -> RAssign (Mb ctx) args -> Mb ctx b
- Data.Binding.Hobbits.Mb: nuMultiWithElim1 :: TypeCtx ctx => (MapRList Name ctx -> arg -> b) -> Mb ctx arg -> Mb ctx b
+ Data.Binding.Hobbits.Mb: nuMultiWithElim1 :: (RAssign Name ctx -> arg -> b) -> Mb ctx arg -> Mb ctx b
- Data.Binding.Hobbits.Mb: nuWithElim :: (Name a -> MapRList Identity args -> b) -> MapRList (Mb (RNil :> a)) args -> Binding a b
+ Data.Binding.Hobbits.Mb: nuWithElim :: (Name a -> RAssign Identity args -> b) -> RAssign (Mb (RNil :> a)) args -> Binding a b
- Data.Binding.Hobbits.Mb: nus :: MapRList f ctx -> (MapRList Name ctx -> b) -> Mb ctx b
+ Data.Binding.Hobbits.Mb: nus :: () => RAssign f ctx -> (RAssign (Name :: k -> Type) ctx -> b) -> Mb ctx b
- Data.Binding.Hobbits.Mb: type Binding a = Mb (RNil :> a)
+ Data.Binding.Hobbits.Mb: type Binding (a :: k) = Mb (RNil :> a)
- Data.Type.RList: (:>) :: (RList a) -> a -> RList a
+ Data.Type.RList: (:>) :: RList a -> a -> RList a
- Data.Type.RList: [:>:] :: MapRList f c -> f a -> MapRList f (c :> a)
+ Data.Type.RList: [:>:] :: RAssign f c -> f a -> RAssign f (c :> a)
- Data.Type.RList: [MNil] :: MapRList f RNil
+ Data.Type.RList: [MNil] :: RAssign f RNil
- Data.Type.RList: data Member ctx a
+ Data.Type.RList: data Member (ctx :: RList k1) (a :: k2)
- Data.Type.RList: empty :: MapRList f RNil
+ Data.Type.RList: empty :: RAssign f RNil
- Data.Type.RList: members :: MapRList f c -> MapRList (Member c) c
+ Data.Type.RList: members :: RAssign f c -> RAssign (Member c) c
- Data.Type.RList: mkAppend :: MapRList f c2 -> Append c1 c2 (c1 :++: c2)
+ Data.Type.RList: mkAppend :: RAssign f c2 -> Append c1 c2 (c1 :++: c2)
- Data.Type.RList: mkMonoAppend :: Proxy c1 -> MapRList f c2 -> Append c1 c2 (c1 :++: c2)
+ Data.Type.RList: mkMonoAppend :: Proxy c1 -> RAssign f c2 -> Append c1 c2 (c1 :++: c2)
- Data.Type.RList: proxiesFromAppend :: Append c1 c2 c -> MapRList Proxy c2
+ Data.Type.RList: proxiesFromAppend :: Append c1 c2 c -> RAssign Proxy c2
- Data.Type.RList: singleton :: f a -> MapRList f (RNil :> a)
+ Data.Type.RList: singleton :: f a -> RAssign f (RNil :> a)
- Data.Type.RList: typeCtxProxies :: TypeCtx ctx => MapRList Proxy ctx
+ Data.Type.RList: typeCtxProxies :: TypeCtx ctx => RAssign Proxy ctx

Files

− Data/Binding/Hobbits.hs
@@ -1,55 +0,0 @@-{-# LANGUAGE TypeOperators #-}---- |--- Module      : Data.Binding.Hobbits--- Copyright   : (c) 2011 Edwin Westbrook, Nicolas Frisby, and Paul Brauner------ License     : BSD3------ Maintainer  : emw4@rice.edu--- Stability   : experimental--- Portability : GHC------ This library implements multi-bindings as described in the paper--- E. Westbrook, N. Frisby, P. Brauner, \"Hobbits for Haskell: A Library for--- Higher-Order Encodings in Functional Programming Languages\".--module Data.Binding.Hobbits (-  -- * Values under multi-bindings-  module Data.Binding.Hobbits.Mb,-  -- | The 'Data.Binding.Hobbits.Mb.Mb' type modeling multi-bindings is the-  -- central abstract type of the library--  -- * Closed terms-  module Data.Binding.Hobbits.Closed,-  -- | The 'Data.Binding.Hobbits.Closed.Cl' type models-  -- super-combinators, which are safe functions to apply under-  -- 'Data.Binding.Hobbits.Mb.Mb'.--  -- * Pattern-matching multi-bindings and closed terms-  module Data.Binding.Hobbits.QQ,-  -- | The 'Data.Binding.Hobbits.QQ.nuP' quasiquoter allows safe pattern-  -- matching on 'Data.Binding.Hobbits.Mb.Mb'-  -- values. 'Data.Binding.Hobbits.QQ.superCombP' is similar.--  -- * Lifting values out of multi-bindings-  module Data.Binding.Hobbits.Liftable,--  -- * Ancilliary modules-  module Data.Proxy, module Data.Type.Equality,-  module Data.Type.RList,-  -- | Type lists track the types of bound variables.-  module Data.Binding.Hobbits.NuMatching-  -- | The "Data.Binding.Hobbits.NuMatching" module exposes the-  -- | NuMatching class, which allows pattern-matching on (G)ADTs in-  -- | the bodies of multi-bindings-                            ) where--import Data.Proxy-import Data.Type.Equality-import Data.Type.RList-import Data.Binding.Hobbits.Mb-import Data.Binding.Hobbits.Closed-import Data.Binding.Hobbits.QQ-import Data.Binding.Hobbits.Liftable-import Data.Binding.Hobbits.NuMatching
− Data/Binding/Hobbits/Closed.hs
@@ -1,64 +0,0 @@-{-# LANGUAGE TemplateHaskell, ViewPatterns #-}---- |--- Module      : Data.Binding.Hobbits.Closed--- Copyright   : (c) 2014 Edwin Westbrook, Nicolas Frisby, and Paul Brauner------ License     : BSD3------ Maintainer  : emw4@rice.edu--- Stability   : experimental--- Portability : GHC------ This module uses Template Haskell to distinguish closed terms, so that the--- library can trust such functions to not contain any @Name@ values in their--- closure.--module Data.Binding.Hobbits.Closed (-  -- * Abstract types-  Closed(),-  -- * Operators involving 'Closed'-  unClosed, mkClosed, noClosedNames, clApply, clMbApply, clApplyCl,-  -- * Typeclass for inherently closed types-  Closable(..)-) where--import Data.Binding.Hobbits.Internal.Name-import Data.Binding.Hobbits.Internal.Mb-import Data.Binding.Hobbits.Internal.Closed-import Data.Binding.Hobbits.Mb---- | @noClosedNames@ encodes the hobbits guarantee that no name can escape its--- multi-binding.-noClosedNames :: Closed (Name a) -> b-noClosedNames (Closed n) =-  -- We compare n to itself to force evaluation, in case the body of-  -- the closed value is non-terminating...-  case cmpName n n of-    _ ->-      error $-      "... Clever girl!" ++-      "The `noClosedNames' invariant has somehow been violated."---- | Closed terms are closed (sorry) under application.-clApply :: Closed (a -> b) -> Closed a -> Closed b--- could be defined with cl were it not for the GHC stage restriction-clApply (Closed f) (Closed a) = Closed (f a)---- | Closed multi-bindings are also closed under application.-clMbApply :: Closed (Mb ctx (a -> b)) -> Closed (Mb ctx a) ->-             Closed (Mb ctx b)-clMbApply (Closed f) (Closed a) = Closed (mbApply f a)---- | When applying a closed function, the argument can be viewed as locally--- closed-clApplyCl :: Closed (Closed a -> b) -> Closed a -> Closed b-clApplyCl (Closed f) a = Closed (f a)---- | FIXME: this should not be possible!!-closeBug :: a -> Closed a-closeBug = $([| \x -> $(mkClosed [| x |]) |])---- | Typeclass for inherently closed types-class Closable a where-  toClosed :: a -> Closed a
− Data/Binding/Hobbits/Examples/LambdaLifting.hs
@@ -1,228 +0,0 @@-{-# LANGUAGE QuasiQuotes, ViewPatterns #-}-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE TemplateHaskell #-}-{-# LANGUAGE TypeOperators, DataKinds #-}-{-# LANGUAGE GADTs #-}--{-# OPTIONS_GHC -fwarn-incomplete-patterns #-}---- |--- Module      : Data.Binding.Hobbits.Examples.LambdaLifting--- Copyright   : (c) 2011 Edwin Westbrook, Nicolas Frisby, and Paul Brauner------ License     : BSD3------ Maintainer  : emw4@rice.edu--- Stability   : experimental--- Portability : GHC------ The lambda lifting example from the paper E. Westbrook, N. Frisby,--- P. Brauner, \"Hobbits for Haskell: A Library for Higher-Order Encodings in--- Functional Programming Languages\".------------------------------------------------------------------------------ lambda lifting for the lambda calculus with top-level declarations----------------------------------------------------------------------------module Data.Binding.Hobbits.Examples.LambdaLifting (-  -- * Term data types, using 'Data.Binding.Hobbits.Mb'-  module Data.Binding.Hobbits.Examples.LambdaLifting.Terms,-  -- * The lambda-lifting function-  lambdaLift, mbLambdaLift-  ) where--import Data.Binding.Hobbits-import qualified Data.Type.RList as C--import Data.Binding.Hobbits.Examples.LambdaLifting.Terms---- imported for ease of use at terminal-import Data.Binding.Hobbits.Examples.LambdaLifting.Examples--import Control.Monad.Cont (Cont, runCont, cont)----------------------------------------------------------------- "peeling" lambdas off of a term---------------------------------------------------------------data LType a where LType :: LType (L a)-type LC c = MapRList LType c--type family AddArrows (c :: RList *) b-type instance AddArrows RNil b = b-type instance AddArrows (c :> L a) b = AddArrows c (a -> b)--data PeelRet c a where-  PeelRet :: lc ~ (lc0 :> b) => LC lc -> Mb (c :++: lc) (Term a) ->-             PeelRet c (AddArrows lc a)--peelLambdas :: Mb c (Binding (L b) (Term a)) -> PeelRet c (b -> a)-peelLambdas b = peelLambdasH MNil LType (mbCombine b)--peelLambdasH ::-  lc ~ (lc0 :> b) => LC lc0 -> LType b -> Mb (c :++: lc) (Term a) ->-                     PeelRet c (AddArrows lc a)-peelLambdasH lc0 isl [nuP| Lam b |] =-  peelLambdasH (lc0 :>: isl) LType (mbCombine b)-peelLambdasH lc0 ilt t = PeelRet (lc0 :>: ilt) t-----boundParams ::-  lc ~ (lc0 :> b) => LC lc -> (MapRList Name lc -> DTerm a) ->-                     Decl (AddArrows lc a)-boundParams (lc0 :>: LType) k = -- flagged as non-exhaustive, in spite of type-  freeParams lc0 (\ns -> Decl_One $ nu $ \n -> k (ns :>: n))--freeParams ::-  LC lc -> (MapRList Name lc -> Decl a) -> Decl (AddArrows lc a)-freeParams MNil k = k C.empty-freeParams (lc :>: LType) k =-    freeParams lc (\names -> Decl_Cons $ nu $ \x -> k (names :>: x))----------------------------------------------------------------- sub-contexts----------------------------------------------------------------- FIXME: use this type in place of functions-type SubC c' c = MapRList Name c -> MapRList Name c'----------------------------------------------------------------- operations on contexts of free variables---------------------------------------------------------------data MbLName c a where-    MbLName :: Mb c (Name (L a)) -> MbLName c (L a)--type FVList c fvs = MapRList (MbLName c) fvs---- unioning free variable contexts: the data structure-data FVUnionRet c fvs1 fvs2 where-    FVUnionRet :: FVList c fvs -> SubC fvs1 fvs -> SubC fvs2 fvs ->-                  FVUnionRet c fvs1 fvs2--fvUnion :: FVList c fvs1 -> FVList c fvs2 -> FVUnionRet c fvs1 fvs2-fvUnion MNil MNil = FVUnionRet MNil (\_ -> MNil) (\_ -> MNil)-fvUnion MNil (fvs2 :>: fv2) = case fvUnion MNil fvs2 of-  FVUnionRet fvs f1 f2 -> case elemMC fv2 fvs of-    Nothing -> FVUnionRet (fvs :>: fv2)-               (\(xs :>: _) -> f1 xs) (\(xs :>: x) -> f2 xs :>: x)-    Just idx -> FVUnionRet fvs f1 (\xs -> f2 xs :>: C.mapRListLookup idx xs)-fvUnion (fvs1 :>: fv1) fvs2 = case fvUnion fvs1 fvs2 of-  FVUnionRet fvs f1 f2 -> case elemMC fv1 fvs of-    Nothing -> FVUnionRet (fvs :>: fv1)-               (\(xs :>: x) -> f1 xs :>: x) (\(xs :>: _) -> f2 xs)-    Just idx -> FVUnionRet fvs (\xs -> f1 xs :>: C.mapRListLookup idx xs) f2--elemMC :: MbLName c a -> FVList c fvs -> Maybe (Member fvs a)-elemMC _ MNil = Nothing-elemMC mbLN@(MbLName n) (mc :>: MbLName n') = case mbCmpName n n' of-  Just Refl -> Just Member_Base-  Nothing -> fmap Member_Step (elemMC mbLN mc)----------------------------------------------------------------- deBruijn terms, i.e., closed terms---------------------------------------------------------------data STerm c a where-    SWeaken :: SubC c1 c -> STerm c1 a -> STerm c a-    SVar :: Member c (L a) -> STerm c a-    SDVar :: Name (D a) -> STerm c a-    SApp :: STerm c (a -> b) -> STerm c a -> STerm c b--skelSubst :: STerm c a -> MapRList Name c -> DTerm a-skelSubst (SWeaken f db) names = skelSubst db $ f names-skelSubst (SVar inC) names = TVar $ C.mapRListLookup inC names-skelSubst (SDVar dTVar) _ = TDVar dTVar-skelSubst (SApp db1 db2) names = TApp (skelSubst db1 names) (skelSubst db2 names)---- applying a STerm to a context of names-skelAppMultiNames ::-  STerm fvs (AddArrows fvs a) -> FVList c fvs -> STerm fvs a-skelAppMultiNames db args = skelAppMultiNamesH db args (C.members args) where-  skelAppMultiNamesH ::-    STerm fvs (AddArrows args a) -> FVList c args -> MapRList (Member fvs) args ->-    STerm fvs a-  skelAppMultiNamesH fvs MNil _ = fvs-  -- flagged as non-exhaustive, in spite of type-  skelAppMultiNamesH fvs (args :>: MbLName _) (inCs :>: inC) =-    SApp (skelAppMultiNamesH fvs args inCs) (SVar inC)----------------------------------------------------------------- STerms combined with their free variables---------------------------------------------------------------data FVSTerm c lc a where-    FVSTerm :: FVList c fvs -> STerm (fvs :++: lc) a -> FVSTerm c lc a--fvSSepLTVars ::-  MapRList f lc -> FVSTerm (c :++: lc) RNil a -> FVSTerm c lc a-fvSSepLTVars lc (FVSTerm fvs db) = case fvSSepLTVarsH lc Proxy fvs of-  SepRet fvs' f -> FVSTerm fvs' (SWeaken f db)--data SepRet lc c fvs where-  SepRet :: FVList c fvs' -> SubC fvs (fvs' :++: lc) -> SepRet lc c fvs---- | Create a 'Proxy' object for the type list of a 'MapRList' vector.-proxyOfMapRList :: MapRList f c -> Proxy c-proxyOfMapRList _ = Proxy--fvSSepLTVarsH ::-  MapRList f lc -> Proxy c -> FVList (c :++: lc) fvs -> SepRet lc c fvs-fvSSepLTVarsH _ _ MNil = SepRet MNil (\_ -> MNil)-fvSSepLTVarsH lc c (fvs :>: fv@(MbLName n)) = case fvSSepLTVarsH lc c fvs of-  SepRet m f -> case raiseAppName (C.mkMonoAppend c lc) n of-    Left idx ->-      SepRet m (\xs ->-                 f xs :>: C.mapRListLookup (C.weakenMemberL (proxyOfMapRList m) idx) xs)-    Right n ->-      SepRet (m :>: MbLName n)-      (\xs -> case C.splitMapRList c' lc xs of-          (fvs' :>: fv', lcs) ->-            f (appendMapRList fvs' lcs) :>: fv')-    where c' = proxyCons (proxyOfMapRList m) fv--raiseAppName ::-  Append c1 c2 (c1 :++: c2) -> Mb (c1 :++: c2) (Name a) -> Either (Member c2 a) (Mb c1 (Name a))-raiseAppName app n =-  case fmap mbNameBoundP (mbSeparate (proxiesFromAppend app) n) of-    [nuP| Left mem |] -> Left $ mbLift mem-    [nuP| Right n |] -> Right n----------------------------------------------------------------- lambda-lifting, woo hoo!---------------------------------------------------------------type LLBodyRet b c a = Cont (Decls b) (FVSTerm c RNil a)--llBody :: LC c -> Mb c (Term a) -> LLBodyRet b c a-llBody _ [nuP| Var v |] =-  return $ FVSTerm (MNil :>: MbLName v) $ SVar Member_Base-llBody c [nuP| App t1 t2 |] = do-  FVSTerm fvs1 db1 <- llBody c t1-  FVSTerm fvs2 db2 <- llBody c t2-  FVUnionRet names sub1 sub2 <- return $ fvUnion fvs1 fvs2-  return $ FVSTerm names $ SApp (SWeaken sub1 db1) (SWeaken sub2 db2)-llBody c [nuP| Lam b |] = do-  PeelRet lc body <- return $ peelLambdas b-  llret <- llBody (C.appendMapRList c lc) body-  FVSTerm fvs db <- return $ fvSSepLTVars lc llret-  cont $ \k ->-    Decls_Cons (freeParams (fvsToLC fvs) $ \names1 ->-                boundParams lc $ \names2 ->-                skelSubst db (C.appendMapRList names1 names2))-      $ nu $ \d -> k $ FVSTerm fvs (skelAppMultiNames (SDVar d) fvs)-  where-    fvsToLC :: FVList c lc -> LC lc-    fvsToLC = C.mapMapRList mbLNameToProof where-      mbLNameToProof :: MbLName c a -> LType a-      mbLNameToProof (MbLName _) = LType---- the top-level lambda-lifting function-lambdaLift :: Term a -> Decls a-lambdaLift t = runCont (llBody MNil (emptyMb t)) $ \(FVSTerm fvs db) ->-  Decls_Base (skelSubst db (C.mapMapRList (\(MbLName mbn) -> elimEmptyMb mbn) fvs))--mbLambdaLift :: Mb c (Term a) -> Mb c (Decls a)-mbLambdaLift = fmap lambdaLift
− Data/Binding/Hobbits/Examples/LambdaLifting/Examples.hs
@@ -1,52 +0,0 @@--- |--- Module      : Data.Binding.Hobbits.SuperComb--- Copyright   : (c) 2011 Edwin Westbrook, Nicolas Frisby, and Paul Brauner------ License     : BSD3------ Maintainer  : emw4@rice.edu--- Stability   : experimental--- Portability : GHC-----module Data.Binding.Hobbits.Examples.LambdaLifting.Examples where--import Data.Binding.Hobbits.Examples.LambdaLifting.Terms-import Data.Binding.Hobbits----------------------------------------------------------------- examples---------------------------------------------------------------ex1 :: Term ((b1 -> b) -> b1 -> b)-ex1 = lam (\f -> (lam $ \x -> App f x))--ex2 :: Term ((((b2 -> b1) -> b2 -> b1) -> b) -> b)-ex2 = lam (\f1 -> App f1 (lam (\f2 -> lam (\x -> App f2 x))))--ex3 :: Term (b3 -> (((b3 -> b2 -> b1) -> b2 -> b1) -> b) -> b)-ex3 = lam (\x -> lam (\f1 -> App f1 (lam (\f2 -> lam (\y -> f2 `App` x `App` y)))))--ex4-  :: Term-       (((b1 -> b) -> b2 -> b)-        -> (((b1 -> b) -> b2 -> b) -> b2 -> b1)-        -> b2-        -> b1)-ex4 = lam $ \x -> lam $ \f1 ->-      App f1 (lam $ \f2 -> lam $ \y -> f2 `App` (f1 `App` x `App` y))--ex5 :: Term (((b2 -> b1) -> b) -> (b2 -> b1) -> b)-ex5 = lam (\f1 -> lam $ \f2 -> App f1 (lam $ \x -> App f2 x))---- lambda-lift with a free variable (use mbLambdaLift)-ex6 :: Binding (L ((b -> b) -> a)) (Term a)-ex6 = nu (\f -> App (Var f) (lam $ \x -> x))---- lambda-lift with a free variable as part of a lambda's environment-ex7 :: Binding (L ((b2 -> b2) -> b1)) (Term ((b1 -> b) -> b))-ex7 = nu (\f -> lam $ \y -> App y $ App (Var f) (lam $ \x -> x))---- example from paper's Section 4-exP :: Term (((b1 -> b1) -> b) -> (b1 -> b1) -> b)-exP = lam $ \f -> lam $ \g -> App f $ lam $ \x -> App g $ App g x
− Data/Binding/Hobbits/Examples/LambdaLifting/Terms.hs
@@ -1,133 +0,0 @@-{-# LANGUAGE EmptyDataDecls #-}-{-# LANGUAGE TemplateHaskell, Rank2Types, QuasiQuotes, ViewPatterns #-}-{-# LANGUAGE GADTs, KindSignatures, DataKinds #-}---- |--- Module      : Data.Binding.Hobbits.SuperComb--- Copyright   : (c) 2011 Edwin Westbrook, Nicolas Frisby, and Paul Brauner------ License     : BSD3------ Maintainer  : emw4@rice.edu--- Stability   : experimental--- Portability : GHC-----module Data.Binding.Hobbits.Examples.LambdaLifting.Terms-  (L, D,-   Term(..), lam,-   DTerm(..), Decl(..), Decls(..)-  ) where--import Data.Binding.Hobbits-import qualified Data.Type.RList as C---- dummy datatypes for distinguishing Decl names from Lam names-data L a-data D a---- to make a function for MapRList (for pretty)-newtype StringF x = StringF String-unStringF (StringF str) = str------------------------------------------------------------------ source terms----------------------------------------------------------------- Term datatype; no Ds since there's no declarations yet-data Term :: * -> * where-  Var :: Name (L a) -> Term a-  Lam :: Binding (L b) (Term a) -> Term (b -> a)-  App :: Term (b -> a) -> Term b -> Term a--$(mkNuMatching [t| forall a . Term a |])--instance Show (Term a) where show = tpretty---- helps to build terms without explicitly using nu or Var-lam :: (Term a -> Term b) -> Term (a -> b)-lam f = Lam $ nu (f . Var)---- pretty print terms-tpretty :: Term a -> String-tpretty t = pretty' (emptyMb t) C.empty 0-  where pretty' :: Mb c (Term a) -> MapRList StringF c -> Int -> String-        pretty' [nuP| Var b |] varnames n =-            case mbNameBoundP b of-              Left pf  -> unStringF (C.mapRListLookup pf varnames)-              Right n -> "(free-var " ++ show n ++ ")"-        pretty' [nuP| Lam b |] varnames n =-            let x = "x" ++ show n in-            "(\\" ++ x ++ "." ++ pretty' (mbCombine b) (varnames :>: (StringF x)) (n+1) ++ ")"-        pretty' [nuP| App b1 b2 |] varnames n =-            "(" ++ pretty' b1 varnames n ++ " " ++ pretty' b2 varnames n ++ ")"----------------------------------------------------------------- target terms----------------------------------------------------------------- terms under declarations-data DTerm :: * -> * where-  TVar :: Name (L a) -> DTerm a-  TDVar :: Name (D a) -> DTerm a-  TApp :: DTerm (a -> b) -> DTerm a -> DTerm b---- we use this type for a definiens instead of putting lambdas on the front-data Decl :: * -> * where-  Decl_One :: Binding (L a) (DTerm b) -> Decl (a -> b)-  Decl_Cons :: Binding (L a) (Decl b) -> Decl (a -> b)---- top-level declarations with a return value-data Decls :: * -> * where-  Decls_Base :: DTerm a -> Decls a-  Decls_Cons :: Decl b -> Binding (D b) (Decls a) -> Decls a--$(mkNuMatching [t| forall a . DTerm a |])-$(mkNuMatching [t| forall a . Decl a |])-$(mkNuMatching [t| forall a . Decls a |])--instance Show (DTerm a) where show = pretty-instance Show (Decls a) where show = decls_pretty----------------------------------------------------------------- pretty printing----------------------------------------------------------------- pretty print terms-pretty :: DTerm a -> String-pretty t = mpretty (emptyMb t) C.empty--mpretty :: Mb c (DTerm a) -> MapRList StringF c -> String-mpretty [nuP| TVar b |] varnames =-    mprettyName (mbNameBoundP b) varnames-mpretty [nuP| TDVar b |] varnames =-    mprettyName (mbNameBoundP b) varnames-mpretty [nuP| TApp b1 b2 |] varnames =-    "(" ++ mpretty b1 varnames-        ++ " " ++ mpretty b2 varnames ++ ")"--mprettyName (Left pf) varnames = unStringF (C.mapRListLookup pf varnames)-mprettyName (Right n) varnames = "(free-var " ++ (show n) ++ ")"-        ---- pretty print decls-decls_pretty :: Decls a -> String-decls_pretty decls =-    "let\n" ++ (mdecls_pretty (emptyMb decls) C.empty 0)--mdecls_pretty :: Mb c (Decls a) -> MapRList StringF c -> Int -> String-mdecls_pretty [nuP| Decls_Base t |] varnames n =-    "in " ++ (mpretty t varnames)-mdecls_pretty [nuP| Decls_Cons decl rest |] varnames n =-    let fname = "F" ++ show n in-    fname ++ " " ++ (mdecl_pretty decl varnames 0) ++ "\n"-    ++ mdecls_pretty (mbCombine rest) (varnames :>: (StringF fname)) (n+1)--mdecl_pretty :: Mb c (Decl a) -> MapRList StringF c -> Int -> String-mdecl_pretty [nuP| Decl_One t|] varnames n =-  let vname = "x" ++ show n in-  vname ++ " = " ++ mpretty (mbCombine t) (varnames :>: StringF vname)-mdecl_pretty [nuP| Decl_Cons d|] varnames n =-  let vname = "x" ++ show n in-  vname ++ " " ++ mdecl_pretty (mbCombine d) (varnames :>: StringF vname) (n+1)
− Data/Binding/Hobbits/Internal/Closed.hs
@@ -1,78 +0,0 @@-{-# LANGUAGE TemplateHaskell, ViewPatterns #-}---- |--- Module      : Data.Binding.Hobbits.Closed--- Copyright   : (c) 2014 Edwin Westbrook, Nicolas Frisby, and Paul Brauner------ License     : BSD3------ Maintainer  : emw4@rice.edu--- Stability   : experimental--- Portability : GHC------ This module defines the type @'Cl' a@ of closed objects of type--- @a@. Note that, in order to ensure adequacy of the Hobbits--- name-binding approach, this representation is hidden from the user,--- and so this file should never be imported directly by the user.-----module Data.Binding.Hobbits.Internal.Closed where--import Language.Haskell.TH (Q, Exp(..), Type(..))-import qualified Language.Haskell.TH as TH-import qualified Language.Haskell.TH.ExpandSyns as TH--import qualified Data.Generics as SYB-import qualified Language.Haskell.TH.Syntax as TH--{-| The type @Closed a@ represents a closed term of type @a@, i.e., an expression-of type @a@ with no free (Haskell) variables.  Since this cannot be checked-directly in the Haskell type system, the @Closed@ data type is hidden, and the-user can only create closed terms using Template Haskell, through the 'mkClosed'-operator. -}-newtype Closed a = Closed { unClosed :: a }---- | Extract the type of an 'Info' object-#if MIN_VERSION_template_haskell(2,11,0)-reifyNameType :: TH.Name -> Q Type-reifyNameType n =-  TH.reify n >>= \i ->-  case i of-    TH.VarI _ ty _ -> return ty-    _ -> fail $ "hobbits Panic -- could not reify `" ++ show n ++ "'."-#else-reifyNameType :: TH.Name -> Q Type-reifyNameType n =-  TH.reify n >>= \i ->-  case i of-    TH.VarI _ ty _ _ -> return ty-    _ -> fail $ "hobbits Panic -- could not reify `" ++ show n ++ "'."-#endif---- | @mkClosed@ is used with Template Haskell quotations to create closed terms--- of type 'Closed'. A quoted expression is closed if all of the names occuring in--- it are either:------   1) bound globally or---   2) bound within the quotation or---   3) also of type 'Closed'.-mkClosed :: Q Exp -> Q Exp-mkClosed e = AppE (ConE 'Closed) `fmap` e >>= SYB.everywhereM (SYB.mkM w) where-  w e@(VarE n@(TH.Name _ flav)) = case flav of-    TH.NameG {} -> return e -- bound globally-    TH.NameU {} -> return e -- bound locally within this quotation-    TH.NameL {} -> closed n >> return e -- bound locally outside this quotation-    _ -> fail $ "`mkClosed' does not allow dynamically bound names: `"-      ++ show n ++ "'."-  w e = return e--  closed n = do-    ty <- reifyNameType n-    TH.expandSyns ty >>= w ty-      where-        w _ (AppT (ConT m) _) | m == ''Closed = return ()-        w top_ty (ForallT _ _ ty') = w top_ty ty'-        w top_ty _ =-          fail $ "`mkClosed` requires non-global variables to have type `Closed'.\n\t`"-          ++ show (TH.ppr n) ++ "' does not. It's type is:\n\t `"-          ++ show (TH.ppr top_ty) ++ "'."
− Data/Binding/Hobbits/Internal/Mb.hs
@@ -1,101 +0,0 @@-{-# LANGUAGE GADTs, DeriveDataTypeable, Rank2Types, ViewPatterns #-}---- |--- Module      : Data.Binding.Hobbits.Internal.Name--- Copyright   : (c) 2014 Edwin Westbrook, Nicolas Frisby, and Paul Brauner------ License     : BSD3------ Maintainer  : westbrook@kestrel.edu--- Stability   : experimental--- Portability : GHC------ This module defines the type @'Mb' ctx a@. In order to ensure--- adequacy of the Hobbits name-binding approach, this representation--- is hidden, and so this file should never be imported directly by--- the user.-----module Data.Binding.Hobbits.Internal.Mb where--import Data.Typeable-import Data.Proxy-import Data.Type.Equality-import Data.Type.RList--import Data.Binding.Hobbits.Internal.Name---{-|-  An @Mb ctx b@ is a multi-binding that binds one name for each type-  in @ctx@, where @ctx@ has the form @'RNil' ':>' t1 ':>' ... ':>' tn@.-  Internally, multi-bindings are represented either as "fresh-  functions", which are functions that quantify over all fresh names-  that have not been used before and map them to the body of the-  binding, or as "fresh pairs", which are pairs of a list of names-  that are guaranteed to be fresh along with a body. Note that fresh-  pairs must come with an 'MbTypeRepr' for the body type, to ensure-  that the names given in the pair can be relaced by fresher names.--}-data Mb ctx b-    = MkMbFun (MapRList Proxy ctx) (MapRList Name ctx -> b)-    | MkMbPair (MbTypeRepr b) (MapRList Name ctx) b-    deriving Typeable---{-|-   This type states that it is possible to replace free names with-   fresh names in an object of type @a@. This type essentially just-   captures a representation of the type a as either a Name type, a-   multi-binding, a function type, or a (G)ADT. In order to be sure-   that only the "right" proofs are used for (G)ADTs, however, this-   type is hidden from the user, and can only be constructed with-   'mkNuMatching'.--}--data MbTypeRepr a where-    MbTypeReprName :: MbTypeRepr (Name a)-    MbTypeReprMb :: MbTypeRepr a -> MbTypeRepr (Mb ctx a)-    MbTypeReprFun :: MbTypeRepr a -> MbTypeRepr b -> MbTypeRepr (a -> b)-    MbTypeReprData :: MbTypeReprData a -> MbTypeRepr a--data MbTypeReprData a =-    MkMbTypeReprData (forall ctx. MapRList Name ctx -> MapRList Name ctx -> a -> a)---{-|-  The call @mapNamesPf data ns ns' a@ replaces each occurrence of a-  free name in @a@ which is listed in @ns@ by the corresponding name-  listed in @ns'@. This is similar to the name-swapping of Nominal-  Logic, except that the swapping does not go both ways.--}-mapNamesPf :: MbTypeRepr a -> MapRList Name ctx -> MapRList Name ctx -> a -> a-mapNamesPf MbTypeReprName MNil MNil n = n-mapNamesPf MbTypeReprName (names :>: m) (names' :>: m') n =-    case cmpName m n of-      Just Refl -> m'-      Nothing -> mapNamesPf MbTypeReprName names names' n-mapNamesPf MbTypeReprName _ _ _ = error "Should not be possible! (in mapNamesPf)"-mapNamesPf (MbTypeReprMb tRepr) names1 names2 (ensureFreshFun -> (proxies, f)) =-    -- README: the fresh function created below is *guaranteed* to not-    -- be passed elements of either names1 or names2, since it should-    -- only ever be passed fresh names-    MkMbFun proxies (\ns -> mapNamesPf tRepr names1 names2 (f ns))-mapNamesPf (MbTypeReprFun tReprIn tReprOut) names names' f =-    (mapNamesPf tReprOut names names') . f . (mapNamesPf tReprIn names' names)-mapNamesPf (MbTypeReprData (MkMbTypeReprData mapFun)) names names' x =-    mapFun names names' x----- | Ensures a multi-binding is in "fresh function" form-ensureFreshFun :: Mb ctx a -> (MapRList Proxy ctx, MapRList Name ctx -> a)-ensureFreshFun (MkMbFun proxies f) = (proxies, f)-ensureFreshFun (MkMbPair tRepr ns body) =-    (mapMapRList (\_ -> Proxy) ns, \ns' -> mapNamesPf tRepr ns ns' body)---- | Ensures a multi-binding is in "fresh pair" form-ensureFreshPair :: Mb ctx a -> (MapRList Name ctx, a)-ensureFreshPair (MkMbPair _ ns body) = (ns, body)-ensureFreshPair (MkMbFun proxies f) =-    let ns = mapMapRList (MkName . fresh_name) proxies in-    (ns, f ns)
− Data/Binding/Hobbits/Internal/Name.hs
@@ -1,134 +0,0 @@-{-# LANGUAGE GADTs, DeriveDataTypeable, FlexibleInstances, TypeOperators #-}---- |--- Module      : Data.Binding.Hobbits.Internal.Name--- Copyright   : (c) 2014 Edwin Westbrook, Nicolas Frisby, and Paul Brauner------ License     : BSD3------ Maintainer  : westbrook@kestrel.edu--- Stability   : experimental--- Portability : GHC------ This module defines the type @'Name' a@ as a wrapper around a fresh--- integer. Note that, in order to ensure adequacy of the Hobbits--- name-binding approach, this representation is hidden from the user,--- and so this file should never be imported directly by the user.-----module Data.Binding.Hobbits.Internal.Name where--import Data.List-import Data.Functor.Constant-import Data.Typeable-import Data.Type.Equality ((:~:))-import Unsafe.Coerce (unsafeCoerce)-import Data.IORef (IORef, newIORef, readIORef, writeIORef)-import System.IO.Unsafe (unsafePerformIO)--import Data.Type.RList----- | A @Name a@ is a bound name that is associated with type @a@.-newtype Name a = MkName Int deriving (Typeable, Eq)--instance Show (Name a) where-  showsPrec _ (MkName n) = showChar '#' . shows n . showChar '#'--instance Show (MapRList Name c) where-    show names = "[" ++ (concat $ intersperse "," $ mapRListToList $-                        mapMapRList (Constant . show) names) ++ "]"------------------------------------------------------------------------------------- Externally visible operators----------------------------------------------------------------------------------{-|-  @cmpName n m@ compares names @n@ and @m@ of types @Name a@ and @Name b@,-  respectively. When they are equal, @Some e@ is returned for @e@ a proof-  of type @a :~: b@ that their types are equal. Otherwise, @None@ is returned.--  For example:--> nu $ \n -> nu $ \m -> cmpName n n   ==   nu $ \n -> nu $ \m -> Some Refl-> nu $ \n -> nu $ \m -> cmpName n m   ==   nu $ \n -> nu $ \m -> None--}-cmpName :: Name a -> Name b -> Maybe (a :~: b)-cmpName (MkName n1) (MkName n2)-  | n1 == n2 = Just $ unsafeCoerce Refl-  | otherwise = Nothing-------------------------------------------------------------------------------------- Hidden, unsafe operators------------------------------------------------------------------------------------- building an arbitrary InCtx proof with a given length--- (this is used internally in HobbitLib)--data ExMember where ExMember :: Member c a -> ExMember---- creating some Member proof of length i-memberFromLen :: Int -> ExMember-memberFromLen 0 = ExMember Member_Base-memberFromLen n = case memberFromLen (n - 1) of-  ExMember mem -> ExMember (Member_Step mem)---- unsafely creating a *specific* member proof from length i;--- this is for when we know the ith element of c must be type a-unsafeLookupC :: Int -> Member c a-unsafeLookupC n = case memberFromLen n of-  ExMember mem -> unsafeCoerce mem----- building a proxy for each type in some unknown context-data ExProxy where ExProxy :: MapRList Proxy ctx -> ExProxy-proxyFromLen :: Int -> ExProxy-proxyFromLen 0 = ExProxy MNil-proxyFromLen n = case proxyFromLen (n - 1) of-                   ExProxy proxy -> ExProxy (proxy :>: Proxy)---- -- unsafely building a proxy for each type in ctx from the length n--- -- of ctx; this is only safe when we know the length of ctx = n--- unsafeProxyFromLen :: Int -> MapC Proxy ctx--- unsafeProxyFromLen n = case proxyFromLen n of---                          ExProxy proxy -> unsafeCoerce proxy---- -- unsafely convert a list of Ints, used to represent names, to--- -- names of certain, given types; note that the first name in the--- -- list becomes the last name in the output, with the same reversal--- -- used in the Mb representation (see, e.g., mbCombine)--- unsafeNamesFromInts :: [Int] -> MapC Name ctx--- unsafeNamesFromInts [] = unsafeCoerce Nil--- unsafeNamesFromInts (x:xs) =---     unsafeCoerce $ unsafeNamesFromInts xs :> MkName x------------------------------------------------------------------------------------ encapsulated impurity------------------------------------------------------------------------------------ README: we *cannot* inline counter, because we want all uses--- of counter to be the same IORef-counter :: IORef Int-{-# NOINLINE counter #-}-counter = unsafePerformIO (newIORef 0)---- README: fresh_name takes a dummy argument that is used in a dummy--- way to avoid let-floating its body (and thus getting a fresh name--- exactly once)--- README: it *is* ok to inline fresh_name because we don't care in--- what order fresh names are created-fresh_name :: a -> Int-fresh_name a = unsafePerformIO $ do -    dummyRef <- newIORef a-    x <- readIORef counter-    writeIORef counter (x+1)-    return x---- -- make one fresh name for each name in a given input list--- fresh_names :: MapC Name ctx -> MapC Name ctx--- fresh_names Nil = Nil--- fresh_names (names :> n) = fresh_names names :> MkName (fresh_name n)
− Data/Binding/Hobbits/Internal/Utilities.hs
@@ -1,13 +0,0 @@-{-# LANGUAGE Rank2Types #-}--module Data.Binding.Hobbits.Internal.Utilities where--import qualified Data.Generics as SYB----everywhereButM :: Monad m =>-  SYB.GenericQ Bool -> SYB.GenericM m -> SYB.GenericM m-everywhereButM q f x-  | q x       = return x-  | otherwise = (SYB.gmapM (everywhereButM q f) x) >>= f
− Data/Binding/Hobbits/Liftable.hs
@@ -1,131 +0,0 @@-{-# LANGUAGE GADTs, TypeOperators, FlexibleInstances, TemplateHaskell #-}-{-# LANGUAGE ViewPatterns, QuasiQuotes, DataKinds #-}---- |--- Module      : Data.Binding.Hobbits.Mb--- Copyright   : (c) 2014 Edwin Westbrook------ License     : BSD3------ Maintainer  : emw4@rice.edu--- Stability   : experimental--- Portability : GHC------ This module defines the type-class Liftable for lifting--- non-binding-related data out of name-bindings. Note that this code--- is not "trusted", i.e., it is not part of the name-binding--- abstraction: instead, it is all written using the primitives--- exported by the Mb--module Data.Binding.Hobbits.Liftable where--import Data.Type.RList-import Data.Binding.Hobbits.Internal.Mb-import Data.Binding.Hobbits.QQ-import Data.Binding.Hobbits.Closed-import Data.Binding.Hobbits.NuMatching--import Data.Ratio---{-|-  The class @Liftable a@ gives a \"lifting function\" for a, which can-  take any data of type @a@ out of a multi-binding of type @'Mb' ctx a@.--}-class NuMatching a => Liftable a where-    mbLift :: Mb ctx a -> a------------------------------------------------------------------------------------ * Lifting instances that must be defined inside the library abstraction boundary----------------------------------------------------------------------------------instance Liftable Char where-    mbLift (ensureFreshPair -> (_, c)) = c--instance Liftable Int where-    mbLift (ensureFreshPair -> (_, i)) = i--instance Liftable Integer where-    mbLift (ensureFreshPair -> (_, i)) = i--instance Liftable (Closed a) where-    mbLift (ensureFreshPair -> (_, c)) = c------------------------------------------------------------------------------------- * Lifting instances and related functions that could be defined outside the library------------------------------------------------------------------------------------ README: this requires overlapping instances, because it clashes--- with Liftable2, but this instance is better because it does not--- require c nor a to be liftable-instance Liftable (Member c a) where-    mbLift [nuP| Member_Base |] = Member_Base-    mbLift [nuP| Member_Step m |] = Member_Step (mbLift m)---- | Lift a list (but not its elements) out of a multi-binding-mbList :: NuMatching a => Mb c [a] -> [Mb c a]-mbList [nuP| [] |] = []-mbList [nuP| x : xs |] = x : mbList xs--instance (Integral a, NuMatching a) => NuMatching (Ratio a) where-  nuMatchingProof =-    isoMbTypeRepr (\r -> (numerator r, denominator r)) (\(n,d) -> n%d)-instance (Integral a, Liftable a) => Liftable (Ratio a) where-  mbLift mb_r =-    (\(n,d) -> n%d) $ mbLift $ fmap (\r -> (numerator r, denominator r)) mb_r--instance Liftable a => Liftable [a] where-    mbLift [nuP| [] |] = []-    mbLift [nuP| x : xs |] = (mbLift x) : (mbLift xs)--instance Liftable () where-    mbLift [nuP| () |] = ()--instance (Liftable a, Liftable b) => Liftable (a,b) where-    mbLift [nuP| (x,y) |] = (mbLift x, mbLift y)--instance Liftable Bool where-  mbLift [nuP| True |] = True-  mbLift [nuP| False |] = False--instance Liftable a => Liftable (Maybe a) where-  mbLift [nuP| Nothing |] = Nothing-  mbLift [nuP| Just mb_a |] = Just $ mbLift mb_a--instance (Liftable a, Liftable b) => Liftable (Either a b) where-  mbLift [nuP| Left mb_a |] = Left $ mbLift mb_a-  mbLift [nuP| Right mb_b |] = Right $ mbLift mb_b---- README: these lead to overlapping instances...--{---{-|-  The class @Liftable1 f@ gives a lifting function for each type @f a@-  when @a@ itself is @Liftable@.--}-class Liftable1 f where-    mbLift1 :: Liftable a => Mb ctx (f a) -> f a--instance (Liftable1 f, Liftable a) => Liftable (f a) where-    mbLift = mbLift1--instance Liftable1 [] where-    mbLift1 [nuP| [] |] = []-    mbLift1 [nuP| x : xs |] = (mbLift x) : (mbLift1 xs)--{-|-  The class @Liftable2 f@ gives a lifting function for each type @f a b@-  when @a@ and @b@ are @Liftable@.--}-class Liftable2 f where-    mbLift2 :: (Liftable a, Liftable b) => Mb ctx (f a b) -> f a b--instance Liftable2 (,) where-    mbLift2 [nuP| (x,y) |] = (mbLift x, mbLift y)--instance (Liftable2 f, Liftable a) => Liftable1 (f a) where-    mbLift1 = mbLift2---}
− Data/Binding/Hobbits/Mb.hs
@@ -1,298 +0,0 @@-{-# LANGUAGE GADTs, TypeOperators, FlexibleInstances, ViewPatterns, DataKinds #-}---- |--- Module      : Data.Binding.Hobbits.Mb--- Copyright   : (c) 2011 Edwin Westbrook, Nicolas Frisby, and Paul Brauner------ License     : BSD3------ Maintainer  : emw4@rice.edu--- Stability   : experimental--- Portability : GHC------ This module defines multi-bindings as the type 'Mb', as well as a number of--- operations on multi-bindings. See the paper E. Westbrook, N. Frisby,--- P. Brauner, \"Hobbits for Haskell: A Library for Higher-Order Encodings in--- Functional Programming Languages\" for more information.--module Data.Binding.Hobbits.Mb (-  -- * Abstract types-  Name(),      -- hides Name implementation-  Binding(),   -- hides Binding implementation-  Mb(),        -- hides MultiBind implementation-  -- * Multi-binding constructors-  nu, nuMulti, nus, emptyMb,-  -- * Queries on names-  cmpName, mbNameBoundP, mbCmpName,-  -- * Operations on multi-bindings-  elimEmptyMb, mbCombine, mbSeparate, mbToProxy, mbSwap, mbApply,-  -- * Eliminators for multi-bindings-  nuMultiWithElim, nuWithElim, nuMultiWithElim1, nuWithElim1-) where--import Control.Applicative-import Control.Monad.Identity--import Data.Type.Equality ((:~:)(..))-import Data.Proxy (Proxy(..))--import Unsafe.Coerce (unsafeCoerce)--import Data.Type.RList--import Data.Binding.Hobbits.Internal.Name-import Data.Binding.Hobbits.Internal.Mb---import qualified Data.Binding.Hobbits.Internal as I------------------------------------------------------------------------------------ creating bindings------------------------------------------------------------------------------------ | A @Binding@ is simply a multi-binding that binds one name-type Binding a = Mb (RNil :> a)---- note: we reverse l to show the inner-most bindings last-instance Show a => Show (Mb c a) where-  showsPrec p (ensureFreshPair -> (names, b)) = showParen (p > 10) $-    showChar '#' . shows names . showChar '.' . shows b--{-|-  @nu f@ creates a binding which binds a fresh name @n@ and whose-  body is the result of @f n@.--}-nu :: (Name a -> b) -> Binding a b-nu f = MkMbFun (MNil :>: Proxy) (\(MNil :>: n) -> f n)--{-|-  The expression @nuMulti p f@ creates a multi-binding of zero or more-  names, one for each element of the vector @p@. The bound names are-  passed the names to @f@, which returns the body of the-  multi-binding.  The argument @p@, of type @'MapRList' f ctx@, acts as a-  \"phantom\" argument, used to reify the list of types @ctx@ at the-  term level; thus it is unimportant what the type function @f@ is.--}-nuMulti :: MapRList f ctx -> (MapRList Name ctx -> b) -> Mb ctx b-nuMulti proxies f = MkMbFun (mapMapRList (const Proxy) proxies) f---- | @nus = nuMulti@-nus x = nuMulti x------------------------------------------------------------------------------------- Queries on Names----------------------------------------------------------------------------------{-|-  Checks if a name is bound in a multi-binding, returning @Left mem@-  when the name is bound, where @mem@ is a proof that the type of the-  name is in the type list for the multi-binding, and returning-  @Right n@ when the name is not bound, where @n@ is the name.--  For example:--> nu $ \n -> mbNameBoundP (nu $ \m -> m)  ==  nu $ \n -> Left Member_Base-> nu $ \n -> mbNameBoundP (nu $ \m -> n)  ==  nu $ \n -> Right n--}-mbNameBoundP :: Mb ctx (Name a) -> Either (Member ctx a) (Name a)-mbNameBoundP (ensureFreshPair -> (names, n)) = helper names n where-    helper :: MapRList Name c -> Name a -> Either (Member c a) (Name a)-    helper MNil n = Right n-    helper (names :>: (MkName i)) (MkName j)-      | i == j =-        unsafeCoerce $ Left Member_Base-    helper (names :>: _) n =-      case helper names n of-        Left memb -> Left (Member_Step memb)-        Right n -> Right n--- old implementation with lists-{--case elemIndex n names of-  Nothing -> Right (MkName n)-  Just i -> Left (I.unsafeLookupC i)--}---{-|-  Compares two names inside bindings, taking alpha-equivalence into-  account; i.e., if both are the @i@th name, or both are the same name-  not bound in their respective multi-bindings, then they compare as-  equal. The return values are the same as for 'cmpName', so that-  @Some Refl@ is returned when the names are equal and @Nothing@ is-  returned when they are not.--}-mbCmpName :: Mb c (Name a) -> Mb c (Name b) -> Maybe (a :~: b)-mbCmpName b1 b2 = case (mbNameBoundP b1, mbNameBoundP b2) of-  (Left mem1, Left mem2) -> membersEq mem1 mem2-  (Right n1, Right n2) -> cmpName n1 n2-  _ -> Nothing------------------------------------------------------------------------------------- Operations on multi-bindings------------------------------------------------------------------------------------ | Creates an empty binding that binds 0 names.-emptyMb :: a -> Mb RNil a-emptyMb body = MkMbFun MNil (\_ -> body)--{-|-  Eliminates an empty binding, returning its body. Note that-  @elimEmptyMb@ is the inverse of @emptyMb@.--}-elimEmptyMb :: Mb RNil a -> a-elimEmptyMb (ensureFreshPair -> (_, body)) = body----- Extract the proxy objects from an Mb inside of a fresh function-freshFunctionProxies :: MapRList Proxy ctx1 -> (MapRList Name ctx1 -> Mb ctx2 a) ->-                        MapRList Proxy ctx2-freshFunctionProxies proxies1 f =-    case f (mapMapRList (const $ MkName 0) proxies1) of-      MkMbFun proxies2 _ -> proxies2-      MkMbPair _ ns _ -> mapMapRList (const Proxy) ns----- README: inner-most bindings come FIRST--- | Combines a binding inside another binding into a single binding.-mbCombine :: Mb c1 (Mb c2 b) -> Mb (c1 :++: c2) b-mbCombine (MkMbPair tRepr1 l1 (MkMbPair tRepr2 l2 b)) =-  MkMbPair tRepr2 (appendMapRList l1 l2) b-mbCombine (ensureFreshFun -> (proxies1, f1)) =-    -- README: we pass in Names with integer value 0 here in order to-    -- get out the proxies for the inner-most bindings; this is "safe"-    -- because these proxies should never depend on the names-    -- themselves-    let proxies2 = freshFunctionProxies proxies1 f1 in-    MkMbFun-    (appendMapRList proxies1 proxies2)-    (\ns ->-         let (ns1, ns2) = splitMapRList Proxy proxies2 ns in-         let (_, f2) = ensureFreshFun (f1 ns1) in-         f2 ns2)---{-|-  Separates a binding into two nested bindings. The first argument, of-  type @'MapRList' any c2@, is a \"phantom\" argument to indicate how-  the context @c@ should be split.--}-mbSeparate :: MapRList any ctx2 -> Mb (ctx1 :++: ctx2) a ->-              Mb ctx1 (Mb ctx2 a)-mbSeparate c2 (MkMbPair tRepr ns a) =-    MkMbPair (MbTypeReprMb tRepr) ns1 (MkMbPair tRepr ns2 a) where-        (ns1, ns2) = splitMapRList Proxy c2 ns-mbSeparate c2 (MkMbFun proxies f) =-    MkMbFun proxies1 (\ns1 -> MkMbFun proxies2 (\ns2 -> f (appendMapRList ns1 ns2)))-        where-          (proxies1, proxies2) = splitMapRList Proxy c2 proxies----- | Returns a proxy object that enumerates all the types in ctx.-mbToProxy :: Mb ctx a -> MapRList Proxy ctx-mbToProxy (MkMbFun proxies _) = proxies-mbToProxy (MkMbPair _ ns _) = mapMapRList (\_ -> Proxy) ns---{-|-  Take a multi-binding inside another multi-binding and move the-  outer binding inside the ineer one.--}-mbSwap :: Mb ctx1 (Mb ctx2 a) -> Mb ctx2 (Mb ctx1 a)-mbSwap (ensureFreshFun -> (proxies1, f1)) =-    let proxies2 = freshFunctionProxies proxies1 f1 in-    MkMbFun proxies2-      (\ns2 ->-         MkMbFun proxies1-         (\ns1 ->-            snd (ensureFreshFun (f1 ns1)) ns2))--{-|-  Applies a function in a multi-binding to an argument in a-  multi-binding that binds the same number and types of names.--}-mbApply :: Mb ctx (a -> b) -> Mb ctx a -> Mb ctx b-mbApply (ensureFreshFun -> (proxies, f_fun)) (ensureFreshFun -> (_, f_arg)) =-  MkMbFun proxies (\ns -> f_fun ns $ f_arg ns)------------------------------------------------------------------------------------- Functor and Applicative instances----------------------------------------------------------------------------------instance Functor (Mb ctx) where-    fmap f mbArg =-        mbApply (nuMulti (mbToProxy mbArg) (\_ -> f)) mbArg--instance TypeCtx ctx => Applicative (Mb ctx) where-    pure x = nuMulti typeCtxProxies (const x)-    (<*>) = mbApply------------------------------------------------------------------------------------- Eliminators for multi-bindings------------------------------------------------------------------------------------ FIXME: add more examples!!-{-|-  The expression @nuWithElimMulti args f@ takes a sequence @args@ of-  zero or more multi-bindings, each of type @Mb ctx ai@ for the same-  type context @ctx@ of bound names, and a function @f@ and does the-  following:--  * Creates a multi-binding that binds names @n1,...,nn@, one name for-    each type in @ctx@;--  * Substitutes the names @n1,...,nn@ for the names bound by each-    argument in the @args@ sequence, yielding the bodies of the @args@-    (using the new name @n@); and then--  * Passes the sequence @n1,...,nn@ along with the result of-    substituting into @args@ to the function @f@, which then returns-    the value for the newly created binding.--  Note that the types in @args@ must each have a @NuMatching@ instance;-  this is represented with the @NuMatchingList@ type class.--  Here are some examples:--> (<*>) :: Mb ctx (a -> b) -> Mb ctx a -> Mb ctx b-> (<*>) f a =->     nuWithElimMulti ('MNil' :>: f :>: a)->                     (\_ ('MNil' :>: 'Identity' f' :>: 'Identity' a') -> f' a')--}-nuMultiWithElim :: TypeCtx ctx =>-                   (MapRList Name ctx -> MapRList Identity args -> b) ->-                   MapRList (Mb ctx) args -> Mb ctx b-nuMultiWithElim f args =-  MkMbFun typeCtxProxies-          (\ns ->-            f ns $ mapMapRList (\arg ->-                                 Identity $ snd (ensureFreshFun arg) ns) args)---{-|-  Similar to 'nuMultiWithElim' but binds only one name.--}-nuWithElim :: (Name a -> MapRList Identity args -> b) ->-              MapRList (Mb (RNil :> a)) args ->-              Binding a b-nuWithElim f args =-    nuMultiWithElim (\(MNil :>: n) -> f n) args---{-|-  Similar to 'nuMultiWithElim' but takes only one argument--}-nuMultiWithElim1 :: TypeCtx ctx => (MapRList Name ctx -> arg -> b) -> Mb ctx arg ->-                    Mb ctx b-nuMultiWithElim1 f arg =-    nuMultiWithElim (\names (MNil :>: Identity arg) -> f names arg) (MNil :>: arg)---{-|-  Similar to 'nuMultiWithElim' but takes only one argument that binds-  a single name.--}-nuWithElim1 :: (Name a -> arg -> b) -> Binding a arg -> Binding a b-nuWithElim1 f arg =-  nuWithElim (\n (MNil :>: Identity arg) -> f n arg) (MNil :>: arg)
− Data/Binding/Hobbits/NuMatching.hs
@@ -1,525 +0,0 @@-{-# LANGUAGE GADTs, RankNTypes, TypeOperators, ViewPatterns, TypeFamilies #-}-{-# LANGUAGE FlexibleInstances, FlexibleContexts, UndecidableInstances #-}-{-# LANGUAGE TemplateHaskell, ScopedTypeVariables, DataKinds #-}---- |--- Module      : Data.Binding.Hobbits.NuMatching--- Copyright   : (c) 2014 Edwin Westbrook, Nicolas Frisby, and Paul Brauner------ License     : BSD3------ Maintainer  : westbrook@kestrel.edu--- Stability   : experimental--- Portability : GHC------ This module defines the typeclass @'NuMatching' a@, which allows--- pattern-matching on the bodies of multi-bindings when their bodies--- have type a. To ensure adequacy, the actual machinery of how this--- works is hidden from the user, but, for any given (G)ADT @a@, the--- user can use the Template Haskell function 'mkNuMatching' to--- create a 'NuMatching' instance for @a@.------module Data.Binding.Hobbits.NuMatching (-  NuMatching(..), mkNuMatching, NuMatchingList(..), NuMatching1(..),-  MbTypeRepr(), isoMbTypeRepr, NuMatchingObj(..)-) where----import Data.Typeable-import Language.Haskell.TH hiding (Name)-import qualified Language.Haskell.TH as TH-import Control.Monad.State---import Control.Monad.Identity--import Data.Type.RList-import Data.Binding.Hobbits.Internal.Name-import Data.Binding.Hobbits.Internal.Mb-import Data.Binding.Hobbits.Internal.Closed---{-| Just like 'mapNamesPf', except uses the NuMatching class. -}-mapNames :: NuMatching a => MapRList Name ctx -> MapRList Name ctx -> a -> a-mapNames = mapNamesPf nuMatchingProof---- | Helper to match a data declaration in a TH version-insensitive way-#if MIN_VERSION_template_haskell(2,11,0)-matchDataDecl :: Dec -> Maybe (Cxt, TH.Name, [TyVarBndr], [Con])-matchDataDecl (DataD cxt name tyvars _ constrs _) =-  Just (cxt, name, tyvars, constrs)-matchDataDecl (NewtypeD cxt name tyvars _ constr _) =-  Just (cxt, name, tyvars, [constr])-matchDataDecl _ = Nothing-#else-matchDataDecl :: Dec -> Maybe (Cxt, TH.Name, [TyVarBndr], [Con])-matchDataDecl (DataD cxt name tyvars constrs _) =-  Just (cxt, name, tyvars, constrs)-matchDataDecl (NewtypeD cxt name tyvars constr _) =-  Just (cxt, name, tyvars, [constr])-matchDataDecl _ = Nothing-#endif---- | Helper to build an instance declaration in a TH version-insensitive way-#if MIN_VERSION_template_haskell(2,11,0)-mkInstanceD :: Cxt -> Type -> [Dec] -> Dec-mkInstanceD = InstanceD Nothing-#else-mkInstanceD :: Cxt -> Type -> [Dec] -> Dec-mkInstanceD = InstanceD-#endif---{-|-  Instances of the @'NuMatching' a@ class allow pattern-matching on-  multi-bindings whose bodies have type @a@, i.e., on multi-bindings-  of type @'Mb' ctx a@. The structure of this class is mostly hidden-  from the user; see 'mkNuMatching' to see how to create instances-  of the @NuMatching@ class.--}-class NuMatching a where-    nuMatchingProof :: MbTypeRepr a--instance NuMatching (Name a) where-    nuMatchingProof = MbTypeReprName--instance NuMatching (Closed a) where-    -- no need to map free variables in a Closed object-    nuMatchingProof = MbTypeReprData (MkMbTypeReprData $ (\c1 c2 -> id))--instance (NuMatching a, NuMatching b) => NuMatching (a -> b) where-    nuMatchingProof = MbTypeReprFun nuMatchingProof nuMatchingProof--instance NuMatching a => NuMatching (Mb ctx a) where-    nuMatchingProof = MbTypeReprMb nuMatchingProof--instance NuMatching Bool where-    nuMatchingProof = MbTypeReprData (MkMbTypeReprData $ (\_ _ -> id))--instance NuMatching Int where-    nuMatchingProof = MbTypeReprData (MkMbTypeReprData $ (\c1 c2 -> id))--instance NuMatching Integer where-    nuMatchingProof = MbTypeReprData (MkMbTypeReprData $ (\c1 c2 -> id))--instance NuMatching Char where-    nuMatchingProof = MbTypeReprData (MkMbTypeReprData $ (\c1 c2 -> id))--instance NuMatching () where-    nuMatchingProof = MbTypeReprData (MkMbTypeReprData $ (\c1 c2 -> id))--instance (NuMatching a, NuMatching b) => NuMatching (a,b) where-    nuMatchingProof = MbTypeReprData (MkMbTypeReprData $ (\c1 c2 (a,b) -> (mapNames c1 c2 a, mapNames c1 c2 b)))--instance (NuMatching a, NuMatching b, NuMatching c) => NuMatching (a,b,c) where-    nuMatchingProof = MbTypeReprData (MkMbTypeReprData $ (\c1 c2 (a,b,c) -> (mapNames c1 c2 a, mapNames c1 c2 b, mapNames c1 c2 c)))--instance (NuMatching a, NuMatching b, NuMatching c, NuMatching d) => NuMatching (a,b,c,d) where-    nuMatchingProof = MbTypeReprData (MkMbTypeReprData $ (\c1 c2 (a,b,c,d) -> (mapNames c1 c2 a, mapNames c1 c2 b, mapNames c1 c2 c, mapNames c1 c2 d)))--instance NuMatching a => NuMatching (Maybe a) where-    nuMatchingProof = MbTypeReprData-                  (MkMbTypeReprData-                   $ (\c1 c2 x -> case x of-                                    Just x -> Just (mapNames c1 c2 x)-                                    Nothing -> Nothing))--instance (NuMatching a, NuMatching b) => NuMatching (Either a b) where-    nuMatchingProof = MbTypeReprData-                  (MkMbTypeReprData-                   $ (\c1 c2 x -> case x of-                                    Left l -> Left (mapNames c1 c2 l)-                                    Right r -> Right (mapNames c1 c2 r)))--instance NuMatching a => NuMatching [a] where-    nuMatchingProof = MbTypeReprData (MkMbTypeReprData $ (\c1 c2 -> map (mapNames c1 c2)))--instance NuMatching (Member c a) where-    nuMatchingProof = MbTypeReprData (MkMbTypeReprData $ (\c1 c2 -> id))---{--type family NuMatchingListProof args-type instance NuMatchingListProof Nil = ()-type instance NuMatchingListProof (args :> arg) = (NuMatchingListProof args, MbTypeReprData arg)---- the NuMatchingList class, for saying that NuMatching holds for a context of types-class NuMatchingList args where-    nuMatchingListProof :: NuMatchingListProof args--instance NuMatchingList Nil where-    nuMatchingListProof = ()--instance (NuMatchingList args, NuMatching a) => NuMatchingList (args :> a) where-    nuMatchingListProof = (nuMatchingListProof, nuMatchingProof)--}--data NuMatchingObj a = NuMatching a => NuMatchingObj ()---- the NuMatchingList class, for saying that NuMatching holds for a context of types-class NuMatchingList args where-    nuMatchingListProof :: MapRList NuMatchingObj args--instance NuMatchingList RNil where-    nuMatchingListProof = MNil--instance (NuMatchingList args, NuMatching a) => NuMatchingList (args :> a) where-    nuMatchingListProof = nuMatchingListProof :>: NuMatchingObj ()---class NuMatching1 f where-    nuMatchingProof1 :: NuMatching a => NuMatchingObj (f a)---- README: deriving NuMatching from NuMatching1 leads to overlapping instances--- for, e.g., Name a-{--instance (NuMatching1 f, NuMatching a) => NuMatching (f a) where-    nuMatchingProof = nuMatchingProof1 nuMatchingProof--}--instance (NuMatching1 f, NuMatchingList ctx) => NuMatching (MapRList f ctx) where-    nuMatchingProof = MbTypeReprData $ MkMbTypeReprData $ helper nuMatchingListProof where-        helper :: NuMatching1 f =>-                  MapRList NuMatchingObj args -> MapRList Name ctx1 ->-                  MapRList Name ctx1 -> MapRList f args -> MapRList f args-        helper MNil c1 c2 MNil = MNil-        helper (proofs :>: NuMatchingObj ()) c1 c2 (elems :>: (elem :: f a)) =-            case nuMatchingProof1 :: NuMatchingObj (f a) of-              NuMatchingObj () ->-                  (helper proofs c1 c2 elems) :>:-                  mapNames c1 c2 elem----- | Build an 'MbTypeRepr' for type @a@ by using an isomorphism with an--- already-representable type @b@. This is useful for building 'NuMatching'--- instances for, e.g., 'Integral' types, by mapping to and from 'Integer',--- without having to define instances for each one in this module.-isoMbTypeRepr :: NuMatching b => (a -> b) -> (b -> a) -> MbTypeRepr a-isoMbTypeRepr f_to f_from =-  MbTypeReprData $ MkMbTypeReprData $ \names1 names2 a ->-  f_from $ mapNames names1 names2 (f_to a)----- now we define some TH to create NuMatchings--natsFrom i = i : natsFrom (i+1)--fst3 :: (a,b,c) -> a-fst3 (x,_,_) = x--snd3 :: (a,b,c) -> b-snd3 (_,y,_) = y--thd3 :: (a,b,c) -> c-thd3 (_,_,z) = z---type Names = (TH.Name, TH.Name, TH.Name, TH.Name)--mapNamesType a = [t| forall ctx. MapRList Name ctx -> MapRList Name ctx -> $a -> $a |]--{-|-  Template Haskell function for creating NuMatching instances for (G)ADTs.-  Typical usage is to include the following line in the source file for-  (G)ADT @T@ (here assumed to have two type arguments):--> $(mkNuMatching [t| forall a b . T a b |])--  The 'mkNuMatching' call here will create an instance declaration for-  @'NuMatching' (T a b)@. It is also possible to include a context in the-  forall type; for example, if we define the 'ID' data type as follows:--> data ID a = ID a--  then we can create a 'NuMatching' instance for it like this:--> $( mkNuMatching [t| NuMatching a => ID a |])--  Note that, when a context is included, the Haskell parser will add-  the @forall a@ for you.--}-mkNuMatching :: Q Type -> Q [Dec]-mkNuMatching tQ =-    do t <- tQ-       (cxt, cType, tName, constrs, tyvars) <- getMbTypeReprInfoTop t-       fName <- newName "f"-       x1Name <- newName "x1"-       x2Name <- newName "x2"-       clauses <- getClauses (tName, fName, x1Name, x2Name) constrs-       mapNamesT <- mapNamesType (return cType)-       return [mkInstanceD-               cxt (AppT (ConT ''NuMatching) cType)-               [ValD (VarP 'nuMatchingProof)-                (NormalB-                 $ AppE (ConE 'MbTypeReprData)-                   $ AppE (ConE 'MkMbTypeReprData)-                         $ LetE [SigD fName-                                 $ ForallT (map PlainTV tyvars) cxt mapNamesT,-                                 FunD fName clauses]-                               (VarE fName)) []]]--       {--       return (LetE-               [SigD fName-                     (ForallT tyvars reqCxt-                     $ foldl AppT ArrowT-                           [foldl AppT (ConT conName)-                                      (map tyVarToType tyvars)]),-                FunD fname clauses]-               (VarE fname))-        -}-    where-      -- extract the name from a TyVarBndr-      tyBndrToName (PlainTV n) = n-      tyBndrToName (KindedTV n _) = n--      -- fail for getMbTypeReprInfo-      getMbTypeReprInfoFail t extraMsg =-          fail ("mkMbTypeRepr: " ++ show t-                ++ " is not a type constructor for a (G)ADT applied to zero or more distinct type variables" ++ extraMsg)--      -- get info for conName (top-level call)-      getMbTypeReprInfoTop t = getMbTypeReprInfo [] [] t t--      -- get info for conName-      getMbTypeReprInfo ctx tyvars topT (ConT tName) =-          do info <- reify tName-             case info of-               TyConI (matchDataDecl -> Just (_, _, tyvarsReq, constrs)) ->-                 success tyvarsReq constrs-               _ -> getMbTypeReprInfoFail topT (": info for " ++ (show tName) ++ " = " ++ (show info))-          where-            success tyvarsReq constrs =-                let tyvarsRet = if tyvars == [] && ctx == []-                                then map tyBndrToName tyvarsReq-                                else tyvars in-                return (ctx,-                        foldl AppT (ConT tName) (map VarT tyvars),-                        tName, constrs, tyvarsRet)--      getMbTypeReprInfo ctx tyvars topT (AppT f (VarT argName)) =-          if elem argName tyvars then-              getMbTypeReprInfoFail topT ""-          else-              getMbTypeReprInfo ctx (argName:tyvars) topT f--      getMbTypeReprInfo ctx tyvars topT (ForallT _ ctx' t) =-          getMbTypeReprInfo (ctx ++ ctx') tyvars topT t--      getMbTypeReprInfo ctx tyvars topT t = getMbTypeReprInfoFail topT ""--      -- get the name from a data type-      getTCtor t = getTCtorHelper t t []-      getTCtorHelper (ConT tName) topT tyvars = Just (topT, tName, tyvars)-      getTCtorHelper (AppT t1 (VarT var)) topT tyvars =-          getTCtorHelper t1 topT (tyvars ++ [var])-      getTCtorHelper (SigT t1 _) topT tyvars = getTCtorHelper t1 topT tyvars-      getTCtorHelper _ _ _ = Nothing--      -- get a list of Clauses, one for each constructor in constrs-      getClauses :: Names -> [Con] -> Q [Clause]-      getClauses _ [] = return []--      getClauses names (NormalC cName cTypes : constrs) =-        do clause <--             getClauseHelper names (map snd cTypes) (natsFrom 0)-             (\l -> ConP cName (map (VarP . fst3) l))-             (\l -> foldl AppE (ConE cName) (map fst3 l))-           clauses <- getClauses names constrs-           return $ clause : clauses--      getClauses names (RecC cName cVarTypes : constrs) =-        do clause <--             getClauseHelper names (map thd3 cVarTypes) (map fst3 cVarTypes)-             (\l -> RecP cName (map (\(var,_,field) -> (field, VarP var)) l))-             (\l -> RecConE cName (map (\(exp,_,field) -> (field, exp)) l))-           clauses <- getClauses names constrs-           return $ clause : clauses--      getClauses names (InfixC cType1 cName cType2 : constrs) =-        undefined -- FIXME--#if MIN_VERSION_template_haskell(2,11,0)-      getClauses names (GadtC cNames cTypes _ : constrs) =-        do clauses1 <--             forM cNames $ \cName ->-             getClauseHelper names (map snd cTypes) (natsFrom 0)-             (\l -> ConP cName (map (VarP . fst3) l))-             (\l -> foldl AppE (ConE cName) (map fst3 l))-           clauses2 <- getClauses names constrs-           return (clauses1 ++ clauses2)--      getClauses names (RecGadtC cNames cVarTypes _ : constrs) =-        do clauses1 <--             forM cNames $ \cName ->-             getClauseHelper names (map thd3 cVarTypes) (map fst3 cVarTypes)-             (\l -> RecP cName (map (\(var,_,field) -> (field, VarP var)) l))-             (\l -> RecConE cName (map (\(exp,_,field) -> (field, exp)) l))-           clauses2 <- getClauses names constrs-           return (clauses1 ++ clauses2)-#endif--      getClauses names (ForallC _ _ constr : constrs) =-        getClauses names (constr : constrs)--      getClauseHelper :: Names -> [Type] -> [a] ->-                         ([(TH.Name,Type,a)] -> Pat) ->-                         ([(Exp,Type,a)] -> Exp) ->-                         Q Clause-      getClauseHelper names@(tName, fName, x1Name, x2Name) cTypes cData pFun eFun =-          do varNames <- mapM (newName . ("x" ++) . show . fst)-                         $ zip (natsFrom 0) cTypes-             let varsTypesData = zip3 varNames cTypes cData-             let expsTypesData = map (mkExpTypeData names) varsTypesData-             return $ Clause [(VarP x1Name), (VarP x2Name), (pFun varsTypesData)]-                        (NormalB $ eFun expsTypesData) []--      mkExpTypeData :: Names -> (TH.Name,Type,a) -> (Exp,Type,a)-      mkExpTypeData (tName, fName, x1Name, x2Name)-                    (varName, getTCtor -> Just (t, tName', _), cData)-          | tName == tName' =-              -- the type of the arg is the same as the (G)ADT we are-              -- recursing over; apply the recursive function-              (foldl AppE (VarE fName)-                         [(VarE x1Name), (VarE x2Name), (VarE varName)],-               t, cData)-      mkExpTypeData (tName, fName, x1Name, x2Name) (varName, t, cData) =-          -- the type of the arg is not the same as the (G)ADT; call mapNames-          (foldl AppE (VarE 'mapNames)-                     [(VarE x1Name), (VarE x2Name), (VarE varName)],-           t, cData)---- FIXME: old stuff below--type CxtStateQ a = StateT Cxt Q a---- create a MkMbTypeReprData for a (G)ADT-mkMkMbTypeReprDataOld :: Q TH.Name -> Q Exp-mkMkMbTypeReprDataOld conNameQ =-    do conName <- conNameQ-       (cxt, name, tyvars, constrs) <- getMbTypeReprInfo conName-       (clauses, reqCxt) <- runStateT (getClauses cxt name tyvars [] constrs) []-       fname <- newName "f"-       return (LetE-               [SigD fname-                     (ForallT tyvars reqCxt-                     $ foldl AppT ArrowT-                           [foldl AppT (ConT conName)-                                      (map tyVarToType tyvars)]),-                FunD fname clauses]-               (VarE fname))-    where-      -- convert a TyVar to a Name-      tyVarToType (PlainTV n) = VarT n-      tyVarToType (KindedTV n _) = VarT n--      -- get info for conName-      getMbTypeReprInfo conName =-          reify conName >>= \info ->-              case info of-                TyConI (matchDataDecl -> Just (cxt, name, tyvars, constrs)) ->-                    return (cxt, name, tyvars, constrs)-                _ -> fail ("mkMkMbTypeReprData: " ++ show conName-                           ++ " is not a (G)ADT")-      {--      -- report failure-      getMbTypeReprInfoFail t =-          fail ("mkMkMbTypeReprData: " ++ show t-                ++ " is not a fully applied (G)ADT")--      getMbTypeReprInfo (ConT conName) topT =-          reify conName >>= \info ->-              case info of-                TyConI (DataD cxt name tyvars constrs _) ->-                    return (cxt, name, tyvars, constrs)-                _ -> getMbTypeReprInfoFail topT-      getMbTypeReprInfo (AppT t _) topT = getMbTypeReprInfo t topT-      getMbTypeReprInfo (SigT t _) topT = getMbTypeReprInfo t topT-      getMbTypeReprInfo _ topT = getMbTypeReprInfoFail topT-       -}--      -- get a list of Clauses, one for each constructor in constrs-      getClauses :: Cxt -> TH.Name -> [TyVarBndr] -> [TyVarBndr] -> [Con] ->-                    CxtStateQ [Clause]-      getClauses cxt name tyvars locTyvars [] = return []--      getClauses cxt name tyvars locTyvars (NormalC cName cTypes : constrs) =-        do clause <--             getClauseHelper cxt name tyvars locTyvars (map snd cTypes)-             (natsFrom 0)-             (\l -> ConP cName (map (VarP . fst3) l))-             (\l -> foldl AppE (ConE cName) (map (VarE . fst3) l))-           clauses <- getClauses cxt name tyvars locTyvars constrs-           return (clause : clauses)--      getClauses cxt name tyvars locTyvars (RecC cName cVarTypes : constrs) =-        do clause <--             getClauseHelper cxt name tyvars locTyvars (map thd3 cVarTypes)-             (map fst3 cVarTypes)-             (\l -> RecP cName (map (\(var,_,field) -> (field, VarP var)) l))-             (\l -> RecConE cName (map (\(var,_,field) -> (field, VarE var)) l))-           clauses <- getClauses cxt name tyvars locTyvars constrs-           return (clause : clauses)--      getClauses cxt name tyvars locTyvars (InfixC cType1 cName cType2 : _) =-        undefined -- FIXME--      getClauses cxt name tyvars locTyvars (ForallC tyvars2 cxt2 constr-                                            : constrs) =-        do clauses1 <--             getClauses (cxt ++ cxt2) name tyvars (locTyvars ++ tyvars2) [constr]-           clauses2 <- getClauses cxt name tyvars locTyvars constrs-           return (clauses1 ++ clauses2)--#if MIN_VERSION_template_haskell(2,11,0)-      getClauses cxt name tyvars locTyvars (GadtC cNames cTypes _ : constrs) =-        do clauses1 <--             forM cNames $ \cName ->-             getClauseHelper cxt name tyvars locTyvars (map snd cTypes)-             (natsFrom 0) (\l -> ConP cName (map (VarP . fst3) l))-             (\l -> foldl AppE (ConE cName) (map (VarE . fst3) l))-           clauses2 <- getClauses cxt name tyvars locTyvars constrs-           return (clauses1 ++ clauses2)--      getClauses cxt name tyvars locTyvars (RecGadtC cNames cVarTypes _-                                            : constrs) =-        do clauses1 <--             forM cNames $ \cName ->-             getClauseHelper cxt name tyvars locTyvars-             (map thd3 cVarTypes) (map fst3 cVarTypes)-             (\l -> RecP cName (map (\(var,_,field) -> (field, VarP var)) l))-             (\l -> RecConE cName (map (\(var,_,field) -> (field, VarE var)) l))-           clauses2 <- getClauses cxt name tyvars locTyvars constrs-           return (clauses1 ++ clauses2)-#endif--      getClauseHelper :: Cxt -> TH.Name -> [TyVarBndr] -> [TyVarBndr] ->-                         [Type] -> [a] ->-                         ([(TH.Name,Type,a)] -> Pat) ->-                         ([(TH.Name,Type,a)] -> Exp) ->-                         CxtStateQ Clause-      getClauseHelper cxt name tyvars locTyvars cTypes cData pFun eFun =-          do varNames <- mapM (lift . newName . ("x" ++) . show . fst)-                         $ zip (natsFrom 0) cTypes-             () <- ensureCxt cxt locTyvars cTypes-             let varsTypesData = zip3 varNames cTypes cData-             return $ Clause [(pFun varsTypesData)]-                        (NormalB $ eFun varsTypesData) []--      -- ensure that MbTypeRepr a holds for each type a in cTypes-      ensureCxt :: Cxt -> [TyVarBndr] -> [Type] -> CxtStateQ ()-      ensureCxt cxt locTyvars cTypes =-          foldM (const (ensureCxt1 cxt locTyvars)) () cTypes--      -- FIXME: it is not possible (or, at least, not easy) to determine-      -- if MbTypeRepr a is implied from a current Cxt... so we just add-      -- everything we need to the returned Cxt, except for -      ensureCxt1 :: Cxt -> [TyVarBndr] -> Type -> CxtStateQ ()-      ensureCxt1 cxt locTyvars t = undefined-      {--      ensureCxt1 cxt locTyvars t = do-        curCxt = get-        let fullCxt = cxt ++ curCxt-        isOk <- isMbTypeRepr fullCxt --      isMbTypeRepr -       -}
− Data/Binding/Hobbits/PatternParser.hs
@@ -1,42 +0,0 @@--- |--- Module      : Data.Binding.Hobbits.PatternParser--- Copyright   : (c) 2011 Edwin Westbrook, Nicolas Frisby, and Paul Brauner------ License     : BSD3------ Maintainer  : emw4@rice.edu--- Stability   : experimental--- Portability : GHC------ Using the haskell-src-meta package to parse Haskell patterns.--module Data.Binding.Hobbits.PatternParser (parsePattern) where--import Language.Haskell.TH--import qualified Language.Haskell.Exts.Parser as Meta--import qualified Language.Haskell.Meta.Parse as Meta--import qualified Language.Haskell.Meta.Parse as Sloppy-import qualified Language.Haskell.Meta.Syntax.Translate as Translate--import qualified Language.Haskell.Exts.Extension as Exts--#if MIN_VERSION_haskell_src_exts(1,14,0)-parsePatternExtensions =-  map Exts.EnableExtension $ Exts.ViewPatterns : Sloppy.myDefaultExtensions-#else-parsePatternExtensions = Exts.ViewPatterns : Sloppy.myDefaultExtensions-#endif------parsePattern :: String -> String -> Either String Pat-parsePattern fn =-  fmap Translate.toPat . Meta.parseResultToEither .-  Meta.parsePatWithMode (Sloppy.myDefaultParseMode-                    {Meta.parseFilename = fn,-                     Meta.extensions = parsePatternExtensions })
− Data/Binding/Hobbits/QQ.hs
@@ -1,148 +0,0 @@-{-# LANGUAGE TemplateHaskell, FlexibleContexts #-}---- |--- Module      : Data.Binding.Hobbits.QQ--- Copyright   : (c) 2011 Edwin Westbrook, Nicolas Frisby, and Paul Brauner------ License     : BSD3------ Maintainer  : emw4@rice.edu--- Stability   : experimental--- Portability : GHC------ Defines a quasi-quoter for writing patterns that match the bodies of 'Mb'--- multi-bindings. Uses the haskell-src-exts parser. @[nuP| P ]@ defines a--- pattern that will match a multi-binding whose body matches @P@. Any--- variables matched by @P@ will remain inside the binding; thus, for example,--- in the pattern @[nuP| x |]@, @x@ matches the entire multi-binding.------ Examples:------ > case (nu Left) of [nuP| Left x |] -> x  ==  nu id------ @[clP| P |]@ does the same for the 'Closed' type, and @[clNuP| P |]@ works--- for both simultaneously: @'Closed' ('Mb' ctx a)@.--module Data.Binding.Hobbits.QQ (nuP, clP, clNuP) where--import Language.Haskell.TH.Syntax as TH-import Language.Haskell.TH.Ppr as TH-import Language.Haskell.TH.Quote--import qualified Data.Generics as SYB-import Control.Monad.Writer (runWriterT, tell)-import Data.Monoid (Any(..))--import qualified Data.Binding.Hobbits.Internal.Utilities as IU-import Data.Binding.Hobbits.Internal.Mb-import Data.Binding.Hobbits.Internal.Closed-import Data.Binding.Hobbits.PatternParser (parsePattern)-import Data.Binding.Hobbits.NuMatching----- | Helper function to apply an expression to multiple arguments-appEMulti :: Exp -> [Exp] -> Exp-appEMulti = foldl AppE---- | Helper function to apply the (.) operator on expressions-compose :: Exp -> Exp -> Exp-compose f g = VarE '(.) `AppE` f `AppE` g---- | @patQQ str pat@ builds a quasi-quoter named @str@ that parses--- | patterns with @pat@-patQQ :: String -> (String -> Q Pat) -> QuasiQuoter-patQQ n pat = QuasiQuoter (err "Exp") pat (err "Type") (err "Decs")-  where err s = error $ "QQ `" ++ n ++ "' is for patterns, not " ++ s ++ "."----- | A @WrapKit@ specifies a transformation to be applied to variables--- | in a Template Haskell patterns, as follows:------ * @_varView@ gives an expression for a function to be applied, as a---   view pattern, to variables before matching them, including to---   variables bound by @\@@ patterns;------ * @_asXform@ gives a function to transform the bodies of \@---   patterns, i.e., this function is applied to @p@ in pattern @x\@p@;------ * @_topXform@ gives a function to transform the whole pattern after---    @_varView@ and/or @_asXform@ have been applied to sub-patterns;---    as the first argument, @_topXform@ also takes a flag indicating---    whether any transformations have been applied to sub-patterns.----data WrapKit =-  WrapKit {_varView :: Exp, _asXform :: Pat -> Pat, _topXform :: Bool -> Pat -> Pat}---- | Combine two WrapKits, composing the individual components-combineWrapKits :: WrapKit -> WrapKit -> WrapKit-combineWrapKits (WrapKit {_varView = varViewO, _asXform = asXformO, _topXform = topXformO})-           (WrapKit {_varView = varViewI, _asXform = asXformI, _topXform = topXformI}) =-  WrapKit {_varView = varViewO `compose` varViewI,-           _asXform = asXformO . asXformI,-           _topXform = \b -> topXformO b . topXformI b}---- | Apply a 'WrapKit' to a pattern-wrapVars :: Monad m => WrapKit -> Pat -> m Pat-wrapVars (WrapKit {_varView = varView, _asXform = asXform, _topXform = topXform}) pat = do-  (pat', Any usedVarView) <- runWriterT m-  return $ topXform usedVarView pat'-  where-    m = IU.everywhereButM (SYB.mkQ False isExp) (SYB.mkM w) pat-      where isExp :: Exp -> Bool-            -- don't recur into the expression part of view patterns-            isExp _ = True--    -- this should be called if the 'varView' function is ever used-    hit x = tell (Any True) >> return x--    -- wraps up bound names-    w p@VarP{} = hit $ ViewP varView p-    -- wraps for the bound name, then immediately unwraps-    -- for the rest of the pattern-    w (AsP v p) = hit $ ViewP varView $ AsP v $ asXform p-    -- requires the expression to be closed-    w (ViewP (VarE n) p) = return $ ViewP (VarE 'unClosed `AppE` VarE n) p-    w (ViewP e _) = fail $ "view function must be a single name: `" ++ show (TH.ppr e) ++ "'"-    w p = return p---- | Parse a pattern from a string, using 'parsePattern'-parseHere :: String -> Q Pat-parseHere s = do-  fn <- loc_filename `fmap` location-  case parsePattern fn s of-    Left e -> error $ "Parse error: `" ++ e ++-      "'\n\n\t when parsing pattern: `" ++ s ++ "'."-    Right p -> return p----- | A helper function used to ensure two multi-bindings have the same contexts-same_ctx :: Mb ctx a -> Mb ctx b -> Mb ctx b-same_ctx _ x = x---- | Builds a 'WrapKit' for parsing patterns that match over 'Mb'.--- | Takes two fresh names as arguments.-nuKit :: TH.Name -> TH.Name -> WrapKit-nuKit topVar namesVar = WrapKit {_varView = varView, _asXform = asXform, _topXform = topXform} where-  varView = (VarE 'same_ctx `AppE` VarE topVar) `compose`-        (appEMulti (ConE 'MkMbPair) [VarE 'nuMatchingProof, VarE namesVar])-  asXform p = ViewP (VarE 'ensureFreshPair) (TupP [WildP, p])-  topXform b p = if b then AsP topVar $ ViewP (VarE 'ensureFreshPair) (TupP [VarP namesVar, p]) else asXform p---- | Quasi-quoter for patterns that match over 'Mb'-nuP = patQQ "nuP" $ \s -> do-  topVar <- newName "topMb"-  namesVar <- newName "topNames"-  parseHere s >>= wrapVars (nuKit topVar namesVar)---- | Builds a 'WrapKit' for parsing patterns that match over 'Closed'-clKit = WrapKit {_varView = ConE 'Closed, _asXform = asXform, _topXform = const asXform}-  where asXform p = ConP 'Closed [p]---- | Quasi-quoter for patterns that match over 'Closed', built using 'clKit'-clP = patQQ "clP" $ (>>= wrapVars clKit) . parseHere---- | Quasi-quoter for patterns that match over @'Closed' ('Mb' ctx a)@-clNuP = patQQ "clNuP" $ \s -> do-  topVar <- newName "topMb"-  namesVar <- newName "topNames"-  parseHere s >>= wrapVars (clKit `combineWrapKits` nuKit topVar namesVar)
− Data/Type/RList.hs
@@ -1,208 +0,0 @@-{-# LANGUAGE TypeOperators, EmptyDataDecls, RankNTypes #-}-{-# LANGUAGE TypeFamilies, DataKinds, KindSignatures #-}-{-# LANGUAGE GADTs #-}---- |--- Module      : Data.Type.RList--- Copyright   : (c) 2016 Edwin Westbrook------ License     : BSD3------ Maintainer  : westbrook@galois.com--- Stability   : experimental--- Portability : GHC------ A /right list/, or 'RList', is a list where cons adds to the end, or the--- right-hand side, of a list. This is useful conceptually for contexts of--- name-bindings, where the most recent name-binding is intuitively at the end--- of the context.--module Data.Type.RList where--import Data.Type.Equality ((:~:)(..))-import Data.Proxy (Proxy(..))-import Data.Functor.Constant-import Data.Typeable------------------------------------------------------------------------------------ Right-lists as a datatype----------------------------------------------------------------------------------data RList a-  = RNil-  | (RList a) :> a--type family ((r1 :: RList *) :++: (r2 :: RList *)) :: RList *-infixr 5 :++:-type instance (r :++: RNil) = r-type instance (r1 :++: (r2 :> a)) = (r1 :++: r2) :> a--proxyCons :: Proxy r -> f a -> Proxy (r :> a)-proxyCons _ _ = Proxy------------------------------------------------------------------------------------- proofs of membership in a type-level list----------------------------------------------------------------------------------{-|-  A @Member ctx a@ is a \"proof\" that the type @a@ is in the type-  list @ctx@, meaning that @ctx@ equals-->  t0 ':>' a ':>' t1 ':>' ... ':>' tn--  for some types @t0,t1,...,tn@.--}-data Member ctx a where-  Member_Base :: Member (ctx :> a) a-  Member_Step :: Member ctx a -> Member (ctx :> b) a-  deriving Typeable--instance Show (Member r a) where showsPrec p = showsPrecMember (p > 10)--showsPrecMember :: Bool -> Member ctx a -> ShowS-showsPrecMember _ Member_Base = showString "Member_Base"-showsPrecMember p (Member_Step prf) = showParen p $-  showString "Member_Step" . showsPrec 10 prf----toEq :: Member (Nil :> a) b -> b :~: a---toEq Member_Base = Refl---toEq _ = error "Should not happen! (toEq)"--weakenMemberL :: Proxy r1 -> Member r2 a -> Member (r1 :++: r2) a-weakenMemberL _ Member_Base = Member_Base-weakenMemberL tag (Member_Step mem) = Member_Step (weakenMemberL tag mem)--membersEq :: Member ctx a -> Member ctx b -> Maybe (a :~: b)-membersEq Member_Base Member_Base = Just Refl-membersEq (Member_Step mem1) (Member_Step mem2) = membersEq mem1 mem2-membersEq _ _ = Nothing------------------------------------------------------------------ proofs that one list equals the append of two others---------------------------------------------------------------{-|-  An @Append ctx1 ctx2 ctx@ is a \"proof\" that @ctx = ctx1 ':++:' ctx2@.--}-data Append ctx1 ctx2 ctx where-  Append_Base :: Append ctx RNil ctx-  Append_Step :: Append ctx1 ctx2 ctx -> Append ctx1 (ctx2 :> a) (ctx :> a)---- -- | Appends two 'Append' proofs.--- trans ::---   Append ctx1 ctx2 ex_ctx -> Append ex_ctx ctx3 ctx -> Append ctx1 (ctx2 :++: ctx3) ctx--- trans app Append_Base = app--- trans app (Append_Step app') = Append_Step (trans app app')---- -- | Returns a proof that ctx :~: ctx1 :++: ctx2--- appendPf :: Append ctx1 ctx2 ctx -> (ctx :~: ctx1 :++: ctx2)--- appendPf Append_Base = Refl--- appendPf (Append_Step app) = case appendPf app of Refl -> Refl---- -- | Returns the length of an 'Append' proof.--- length :: Append ctx1 ctx2 ctx3 -> Int--- length Append_Base = 0--- length (Append_Step app) = 1 + Data.Type.List.Proof.Append.length app------------------------------------------------------------------------------------ Heterogeneous lists----------------------------------------------------------------------------------{-|-  A @MapRList f r@ is a vector with exactly one element of type @f a@ for-  each type @a@ in the type 'RList' @r@.--}-data MapRList f c where-  MNil :: MapRList f RNil-  (:>:) :: MapRList f c -> f a -> MapRList f (c :> a)---- | Create an empty 'MapRList' vector.-empty :: MapRList f RNil-empty = MNil---- | Create a singleton 'MapRList' vector.-singleton :: f a -> MapRList f (RNil :> a)-singleton x = MNil :>: x---- | Look up an element of a 'MapRList' vector using a 'Member' proof.-mapRListLookup :: Member c a -> MapRList f c -> f a-mapRListLookup Member_Base (_ :>: x) = x-mapRListLookup (Member_Step mem') (mc :>: _) = mapRListLookup mem' mc---mapRListLookup _ _ = error "Should not happen! (mapRListLookup)"---- | Map a function on all elements of a 'MapRList' vector.-mapMapRList :: (forall x. f x -> g x) -> MapRList f c -> MapRList g c-mapMapRList _ MNil = MNil-mapMapRList f (mc :>: x) = mapMapRList f mc :>: f x---- | Map a binary function on all pairs of elements of two 'MapRList' vectors.-mapMapRList2 :: (forall x. f x -> g x -> h x) ->-                MapRList f c -> MapRList g c -> MapRList h c-mapMapRList2 _ MNil MNil = MNil-mapMapRList2 f (xs :>: x) (ys :>: y) = mapMapRList2 f xs ys :>: f x y-mapMapRList2 _ _ _ =-  error "Something is terribly wrong in mapMapRList2: this case should not happen!"---- | Append two 'MapRList' vectors.-appendMapRList :: MapRList f c1 -> MapRList f c2 -> MapRList f (c1 :++: c2)-appendMapRList mc MNil = mc-appendMapRList mc1 (mc2 :>: x) = appendMapRList mc1 mc2 :>: x---- -- | Append two 'MapRList' vectors.--- appendWithPf :: Append c1 c2 c -> MapRList f c1 -> MapRList f c2 -> MapRList f c--- appendWithPf Append_Base mc Nil = mc--- appendWithPf (Append_Step app) mc1 (mc2 :>: x) = appendWithPf app mc1 mc2 :>: x--- appendWithPf  _ _ _ = error "Something is terribly wrong in appendWithPf: this case should not happen!"---- | Make an 'Append' proof from any 'MapRList' vector for the second--- argument of the append.-mkAppend :: MapRList f c2 -> Append c1 c2 (c1 :++: c2)-mkAppend MNil = Append_Base-mkAppend (c :>: _) = Append_Step (mkAppend c)---- | A version of 'mkAppend' that takes in a 'Proxy' argument.-mkMonoAppend :: Proxy c1 -> MapRList f c2 -> Append c1 c2 (c1 :++: c2)-mkMonoAppend _ = mkAppend---- | The inverse of 'mkAppend', that builds an 'MapRList' from an 'Append'-proxiesFromAppend :: Append c1 c2 c -> MapRList Proxy c2-proxiesFromAppend Append_Base = MNil-proxiesFromAppend (Append_Step a) = proxiesFromAppend a :>: Proxy---- | Split an 'MapRList' vector into two pieces. The first argument is a--- phantom argument that gives the form of the first list piece.-splitMapRList :: (c ~ (c1 :++: c2)) => Proxy c1 ->-                 MapRList any c2 -> MapRList f c -> (MapRList f c1, MapRList f c2)-splitMapRList _ MNil mc = (mc, MNil)-splitMapRList _ (any :>: _) (mc :>: x) = (mc1, mc2 :>: x)-  where (mc1, mc2) = splitMapRList Proxy any mc---split _ _ = error "Should not happen! (Map.split)"---- | Create a vector of proofs that each type in @c@ is a 'Member' of @c@.-members :: MapRList f c -> MapRList (Member c) c-members MNil = MNil-members (c :>: _) = mapMapRList Member_Step (members c) :>: Member_Base---- -- | Replace a single element of a 'MapRList' vector.--- replace :: MapRList f c -> Member c a -> f a -> MapRList f c--- replace (xs :>: _) Member_Base y = xs :>: y--- replace (xs :>: x) (Member_Step memb) y = replace xs memb y :>: x--- replace _ _ _ = error "Should not happen! (Map.replace)"---- | Convert an MapRList to a list-mapRListToList :: MapRList (Constant a) c -> [a]-mapRListToList MNil = []-mapRListToList (xs :>: Constant x) = mapRListToList xs ++ [x]---- | A type-class which ensures that ctx is a valid context, i.e., has--- | the form (RNil :> t1 :> ... :> tn) for some types t1 through tn-class TypeCtx ctx where-  typeCtxProxies :: MapRList Proxy ctx--instance TypeCtx RNil where-  typeCtxProxies = MNil--instance TypeCtx ctx => TypeCtx (ctx :> a) where-  typeCtxProxies = typeCtxProxies :>: Proxy
LICENSE view
@@ -1,4 +1,4 @@-Copyright (c) 2014, Eddy Westbrook, Nicolas Frisby, Paul Brauner+Copyright (c) 2014, Eddy Westbrook All rights reserved.  Redistribution and use in source and binary forms, with or without modification,
hobbits.cabal view
@@ -1,5 +1,5 @@ Name:                hobbits-Version:             1.2.4+Version:             1.3 Synopsis:            A library for canonically representing terms with binding  Description: A library for canonically representing terms with binding via a@@ -13,28 +13,32 @@  Category:            Data Structures -Cabal-version: >= 1.6.0.1+Cabal-version: >= 1.10 Build-Type:    Simple  extra-source-files: CHANGELOG  Library-  Build-Depends: base >= 4.7 && < 5-  Build-Depends: template-haskell >= 2.9 && < 2.13--  Build-Depends: syb-  Build-Depends: mtl--  Build-Depends: tagged-  Build-Depends: deepseq--  Build-Depends: haskell-src-exts >= 1.17.1 && < 1.20, haskell-src-meta,-                 th-expand-syns >= 0.3 && < 0.5, transformers+  build-depends:+      base >= 4.7 && < 5+    , template-haskell >= 2.11 && < 3+    , syb+    , mtl+    , tagged+    , deepseq+    , haskell-src-exts >= 1.17.1 && < 2+    , haskell-src-meta+    , th-expand-syns >= 0.3 && < 0.5+    , transformers+    , containers+    , vector    GHC-Options: -fwarn-incomplete-patterns -fwarn-unused-imports -  Extensions: CPP+  hs-source-dirs: src +  default-language: Haskell2010+   Exposed-Modules: Data.Type.RList,                     Data.Binding.Hobbits,@@ -42,9 +46,13 @@                    Data.Binding.Hobbits.Closed,                    Data.Binding.Hobbits.QQ,                    Data.Binding.Hobbits.Liftable,+                   Data.Binding.Hobbits.MonadBind,+                   Data.Binding.Hobbits.NameMap,+                   Data.Binding.Hobbits.NameSet,                     Data.Binding.Hobbits.PatternParser,                    Data.Binding.Hobbits.NuMatching,+                   Data.Binding.Hobbits.NuMatchingInstances,                     Data.Binding.Hobbits.Examples.LambdaLifting,                    Data.Binding.Hobbits.Examples.LambdaLifting.Terms,
+ src/Data/Binding/Hobbits.hs view
@@ -0,0 +1,60 @@+{-# LANGUAGE TypeOperators #-}++-- |+-- Module      : Data.Binding.Hobbits+-- Copyright   : (c) 2011 Edwin Westbrook, Nicolas Frisby, and Paul Brauner+--+-- License     : BSD3+--+-- Maintainer  : emw4@rice.edu+-- Stability   : experimental+-- Portability : GHC+--+-- This library implements multi-bindings as described in the paper+-- E. Westbrook, N. Frisby, P. Brauner, \"Hobbits for Haskell: A Library for+-- Higher-Order Encodings in Functional Programming Languages\".++module Data.Binding.Hobbits (+  -- * Values under multi-bindings+  module Data.Binding.Hobbits.Mb,+  -- | The 'Data.Binding.Hobbits.Mb.Mb' type modeling multi-bindings is the+  -- central abstract type of the library++  -- * Closed terms+  module Data.Binding.Hobbits.Closed,+  -- | The 'Data.Binding.Hobbits.Closed.Cl' type models+  -- super-combinators, which are safe functions to apply under+  -- 'Data.Binding.Hobbits.Mb.Mb'.++  -- * Pattern-matching multi-bindings and closed terms+  module Data.Binding.Hobbits.QQ,+  -- | The 'Data.Binding.Hobbits.QQ.nuP' quasiquoter allows safe pattern+  -- matching on 'Data.Binding.Hobbits.Mb.Mb'+  -- values. 'Data.Binding.Hobbits.QQ.superCombP' is similar.++  -- * Lifting values out of multi-bindings+  module Data.Binding.Hobbits.Liftable,++  -- * Ancilliary modules+  module Data.Proxy, module Data.Type.Equality,+  -- | Type lists track the types of bound variables.++  --module Data.Type.RList,+  RList(..), RAssign(..), Member(..), (:++:), Append(..),+  -- | The "Data.Binding.Hobbits.NuMatching" module exposes the NuMatching+  -- class, which allows pattern-matching on (G)ADTs in the bodies of+  -- multi-bindings+  module Data.Binding.Hobbits.NuMatching,+  module Data.Binding.Hobbits.NuMatchingInstances++                            ) where++import Data.Proxy+import Data.Type.Equality+import Data.Type.RList (RList(..), RAssign(..), Member(..), (:++:), Append(..))+import Data.Binding.Hobbits.Mb+import Data.Binding.Hobbits.Closed+import Data.Binding.Hobbits.QQ+import Data.Binding.Hobbits.Liftable+import Data.Binding.Hobbits.NuMatching+import Data.Binding.Hobbits.NuMatchingInstances()
+ src/Data/Binding/Hobbits/Closed.hs view
@@ -0,0 +1,121 @@+{-# LANGUAGE TemplateHaskell, ViewPatterns, PolyKinds, GADTs, PatternGuards #-}++-- |+-- Module      : Data.Binding.Hobbits.Closed+-- Copyright   : (c) 2014 Edwin Westbrook, Nicolas Frisby, and Paul Brauner+--+-- License     : BSD3+--+-- Maintainer  : emw4@rice.edu+-- Stability   : experimental+-- Portability : GHC+--+-- This module uses Template Haskell to distinguish closed terms, so that the+-- library can trust such functions to not contain any @Name@ values in their+-- closure.++module Data.Binding.Hobbits.Closed (+  -- * Abstract types+  Closed(),+  -- * Operators involving 'Closed'+  unClosed, mkClosed, noClosedNames, clApply, clMbApply, clApplyCl, unsafeClose,+  -- * Typeclass for inherently closed types+  Closable(..)+) where++import Data.Proxy+import Data.Type.RList+import Data.Binding.Hobbits.Internal.Name+import Data.Binding.Hobbits.Internal.Mb+import Data.Binding.Hobbits.Internal.Closed+import Data.Binding.Hobbits.Mb++-- | @noClosedNames@ encodes the hobbits guarantee that no name can escape its+-- multi-binding.+noClosedNames :: Closed (Name a) -> b+noClosedNames (Closed n) =+  -- We compare n to itself to force evaluation, in case the body of+  -- the closed value is non-terminating...+  case cmpName n n of+    _ ->+      error $+      "... Clever girl!" +++      "The `noClosedNames' invariant has somehow been violated."++-- | Closed terms are closed (sorry) under application.+clApply :: Closed (a -> b) -> Closed a -> Closed b+-- could be defined with cl were it not for the GHC stage restriction+clApply (Closed f) (Closed a) = Closed (f a)++-- | Closed multi-bindings are also closed under application.+clMbApply :: Closed (Mb ctx (a -> b)) -> Closed (Mb ctx a) ->+             Closed (Mb ctx b)+clMbApply (Closed f) (Closed a) = Closed (mbApply f a)++-- | When applying a closed function, the argument can be viewed as locally+-- closed+clApplyCl :: Closed (Closed a -> b) -> Closed a -> Closed b+clApplyCl (Closed f) a = Closed (f a)++-- | FIXME: this should not be possible!!+closeBug :: a -> Closed a+closeBug = $([| \x -> $(mkClosed [| x |]) |])++-- | Mark an object as closed without actually traversing it. This is unsafe if+-- the object does in fact contain any names.+unsafeClose :: a -> Closed a+unsafeClose = Closed++-- | Typeclass for inherently closed types+class Closable a where+  toClosed :: a -> Closed a++instance Closable Integer where+  toClosed i = Closed i++instance Closable (Member ctx a) where+  -- NOTE: this is actually definable with mkClosed, but this is more efficient+  toClosed memb = Closed memb++instance Closable (Proxy a) where+  toClosed Proxy = $(mkClosed [| Proxy |])++instance Closable (Closed a) where+  toClosed = clApplyCl $(mkClosed [| id |])++instance Closable Bool where+  toClosed True = $(mkClosed [| True |])+  toClosed False = $(mkClosed [| False |])++instance Closable Char where+  toClosed = unsafeClose++instance Closable Int where+  toClosed = unsafeClose++instance Closable a => Closable [a] where+  toClosed [] = $(mkClosed [| [] |])+  toClosed (a:as) =+    $(mkClosed [| (:) |]) `clApply` toClosed a `clApply` toClosed as++-- | Object-level reification of the 'Closable' typeclass+data IsClosable a where IsClosable :: Closable a => IsClosable a++-- | Type functors @f@ where @f a@ is always 'Closable' for any @a@+class ClosableAny1 f where+  closableAny1 :: f a -> IsClosable (f a)++-- | Helper function to use the proof returned by 'closableAny1'+toClosedAny1 :: ClosableAny1 f => f a -> Closed (f a)+toClosedAny1 x | IsClosable <- closableAny1 x = toClosed x++instance ClosableAny1 Proxy where+  closableAny1 _ = IsClosable++instance ClosableAny1 (Member ctx) where+  closableAny1 _ = IsClosable++instance ClosableAny1 f => Closable (RAssign f ctx) where+  toClosed MNil = $(mkClosed [| MNil |])+  toClosed (xs :>: x) =+    $(mkClosed [| (:>:) |]) `clApply` toClosed xs `clApply` toClosedAny1 x
+ src/Data/Binding/Hobbits/Examples/LambdaLifting.hs view
@@ -0,0 +1,231 @@+{-# LANGUAGE QuasiQuotes, ViewPatterns #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE TypeOperators, DataKinds #-}+{-# LANGUAGE GADTs #-}++{-# OPTIONS_GHC -fwarn-incomplete-patterns #-}++-- |+-- Module      : Data.Binding.Hobbits.Examples.LambdaLifting+-- Copyright   : (c) 2011 Edwin Westbrook, Nicolas Frisby, and Paul Brauner+--+-- License     : BSD3+--+-- Maintainer  : emw4@rice.edu+-- Stability   : experimental+-- Portability : GHC+--+-- The lambda lifting example from the paper E. Westbrook, N. Frisby,+-- P. Brauner, \"Hobbits for Haskell: A Library for Higher-Order Encodings in+-- Functional Programming Languages\".++-------------------------------------------------------------------------+-- lambda lifting for the lambda calculus with top-level declarations+-------------------------------------------------------------------------++module Data.Binding.Hobbits.Examples.LambdaLifting (+  -- * Term data types, using 'Data.Binding.Hobbits.Mb'+  module Data.Binding.Hobbits.Examples.LambdaLifting.Terms,+  -- * The lambda-lifting function+  lambdaLift, mbLambdaLift+  ) where++import Data.Binding.Hobbits+import qualified Data.Type.RList as C++import Data.Binding.Hobbits.Examples.LambdaLifting.Terms++-- imported for ease of use at terminal+import Data.Binding.Hobbits.Examples.LambdaLifting.Examples++import Control.Monad.Cont (Cont, runCont, cont)++------------------------------------------------------------+-- "peeling" lambdas off of a term+------------------------------------------------------------++data LType a where LType :: LType (L a)+type LC c = RAssign LType c++type family AddArrows (c :: RList *) b+type instance AddArrows RNil b = b+type instance AddArrows (c :> L a) b = AddArrows c (a -> b)++data PeelRet c a where+  PeelRet :: lc ~ (lc0 :> b) => LC lc -> Mb (c :++: lc) (Term a) ->+             PeelRet c (AddArrows lc a)++peelLambdas :: Mb c (Binding (L b) (Term a)) -> PeelRet c (b -> a)+peelLambdas b = peelLambdasH MNil LType (mbCombine b)++peelLambdasH ::+  lc ~ (lc0 :> b) => LC lc0 -> LType b -> Mb (c :++: lc) (Term a) ->+                     PeelRet c (AddArrows lc a)+peelLambdasH lc0 isl [nuP| Lam b |] =+  peelLambdasH (lc0 :>: isl) LType (mbCombine b)+peelLambdasH lc0 ilt t = PeelRet (lc0 :>: ilt) t+++++boundParams ::+  lc ~ (lc0 :> b) => LC lc -> (RAssign Name lc -> DTerm a) ->+                     Decl (AddArrows lc a)+boundParams (lc0 :>: LType) k = -- flagged as non-exhaustive, in spite of type+  freeParams lc0 (\ns -> Decl_One $ nu $ \n -> k (ns :>: n))++freeParams ::+  LC lc -> (RAssign Name lc -> Decl a) -> Decl (AddArrows lc a)+freeParams MNil k = k C.empty+freeParams (lc :>: LType) k =+    freeParams lc (\names -> Decl_Cons $ nu $ \x -> k (names :>: x))++------------------------------------------------------------+-- sub-contexts+------------------------------------------------------------++-- FIXME: use this type in place of functions+type SubC c' c = RAssign Name c -> RAssign Name c'++------------------------------------------------------------+-- operations on contexts of free variables+------------------------------------------------------------++data MbLName c a where+    MbLName :: Mb c (Name (L a)) -> MbLName c (L a)++type FVList c fvs = RAssign (MbLName c) fvs++-- unioning free variable contexts: the data structure+data FVUnionRet c fvs1 fvs2 where+    FVUnionRet :: FVList c fvs -> SubC fvs1 fvs -> SubC fvs2 fvs ->+                  FVUnionRet c fvs1 fvs2++fvUnion :: FVList c fvs1 -> FVList c fvs2 -> FVUnionRet c fvs1 fvs2+fvUnion MNil MNil = FVUnionRet MNil (\_ -> MNil) (\_ -> MNil)+fvUnion MNil (fvs2 :>: fv2) = case fvUnion MNil fvs2 of+  FVUnionRet fvs f1 f2 -> case elemMC fv2 fvs of+    Nothing -> FVUnionRet (fvs :>: fv2)+               (\(xs :>: _) -> f1 xs) (\(xs :>: x) -> f2 xs :>: x)+    Just idx -> FVUnionRet fvs f1 (\xs -> f2 xs :>: C.get idx xs)+fvUnion (fvs1 :>: fv1) fvs2 = case fvUnion fvs1 fvs2 of+  FVUnionRet fvs f1 f2 -> case elemMC fv1 fvs of+    Nothing -> FVUnionRet (fvs :>: fv1)+               (\(xs :>: x) -> f1 xs :>: x) (\(xs :>: _) -> f2 xs)+    Just idx -> FVUnionRet fvs (\xs -> f1 xs :>: C.get idx xs) f2++elemMC :: MbLName c a -> FVList c fvs -> Maybe (Member fvs a)+elemMC _ MNil = Nothing+elemMC mbLN@(MbLName n) (mc :>: MbLName n') = case mbCmpName n n' of+  Just Refl -> Just Member_Base+  Nothing -> fmap Member_Step (elemMC mbLN mc)++------------------------------------------------------------+-- deBruijn terms, i.e., closed terms+------------------------------------------------------------++data STerm c a where+    SWeaken :: SubC c1 c -> STerm c1 a -> STerm c a+    SVar :: Member c (L a) -> STerm c a+    SDVar :: Name (D a) -> STerm c a+    SApp :: STerm c (a -> b) -> STerm c a -> STerm c b++skelSubst :: STerm c a -> RAssign Name c -> DTerm a+skelSubst (SWeaken f db) names = skelSubst db $ f names+skelSubst (SVar inC) names = TVar $ C.get inC names+skelSubst (SDVar dTVar) _ = TDVar dTVar+skelSubst (SApp db1 db2) names = TApp (skelSubst db1 names) (skelSubst db2 names)++-- applying a STerm to a context of names+skelAppMultiNames ::+  STerm fvs (AddArrows fvs a) -> FVList c fvs -> STerm fvs a+skelAppMultiNames db args = skelAppMultiNamesH db args (C.members args) where+  skelAppMultiNamesH ::+    STerm fvs (AddArrows args a) -> FVList c args -> RAssign (Member fvs) args ->+    STerm fvs a+  skelAppMultiNamesH fvs MNil _ = fvs+  -- flagged as non-exhaustive, in spite of type+  skelAppMultiNamesH fvs (args :>: MbLName _) (inCs :>: inC) =+    SApp (skelAppMultiNamesH fvs args inCs) (SVar inC)++------------------------------------------------------------+-- STerms combined with their free variables+------------------------------------------------------------++proxyCons :: Proxy r -> f a -> Proxy (r :> a)+proxyCons _ _ = Proxy++data FVSTerm c lc a where+    FVSTerm :: FVList c fvs -> STerm (fvs :++: lc) a -> FVSTerm c lc a++fvSSepLTVars ::+  RAssign f lc -> FVSTerm (c :++: lc) RNil a -> FVSTerm c lc a+fvSSepLTVars lc (FVSTerm fvs db) = case fvSSepLTVarsH lc Proxy fvs of+  SepRet fvs' f -> FVSTerm fvs' (SWeaken f db)++data SepRet lc c fvs where+  SepRet :: FVList c fvs' -> SubC fvs (fvs' :++: lc) -> SepRet lc c fvs++-- | Create a 'Proxy' object for the type list of a 'RAssign' vector.+proxyOfRAssign :: RAssign f c -> Proxy c+proxyOfRAssign _ = Proxy++fvSSepLTVarsH ::+  RAssign f lc -> Proxy c -> FVList (c :++: lc) fvs -> SepRet lc c fvs+fvSSepLTVarsH _ _ MNil = SepRet MNil (\_ -> MNil)+fvSSepLTVarsH lc c (fvs :>: fv@(MbLName n)) = case fvSSepLTVarsH lc c fvs of+  SepRet m f -> case raiseAppName (C.mkMonoAppend c lc) n of+    Left idx ->+      SepRet m (\xs ->+                 f xs :>: C.get (C.weakenMemberL (proxyOfRAssign m) idx) xs)+    Right n ->+      SepRet (m :>: MbLName n)+      (\xs -> case C.split c' lc xs of+          (fvs' :>: fv', lcs) ->+            f (C.append fvs' lcs) :>: fv')+    where c' = proxyCons (proxyOfRAssign m) fv++raiseAppName ::+  Append c1 c2 (c1 :++: c2) -> Mb (c1 :++: c2) (Name a) -> Either (Member c2 a) (Mb c1 (Name a))+raiseAppName app n =+  case fmap mbNameBoundP (mbSeparate (C.proxiesFromAppend app) n) of+    [nuP| Left mem |] -> Left $ mbLift mem+    [nuP| Right n |] -> Right n++------------------------------------------------------------+-- lambda-lifting, woo hoo!+------------------------------------------------------------++type LLBodyRet b c a = Cont (Decls b) (FVSTerm c RNil a)++llBody :: LC c -> Mb c (Term a) -> LLBodyRet b c a+llBody _ [nuP| Var v |] =+  return $ FVSTerm (MNil :>: MbLName v) $ SVar Member_Base+llBody c [nuP| App t1 t2 |] = do+  FVSTerm fvs1 db1 <- llBody c t1+  FVSTerm fvs2 db2 <- llBody c t2+  FVUnionRet names sub1 sub2 <- return $ fvUnion fvs1 fvs2+  return $ FVSTerm names $ SApp (SWeaken sub1 db1) (SWeaken sub2 db2)+llBody c [nuP| Lam b |] = do+  PeelRet lc body <- return $ peelLambdas b+  llret <- llBody (C.append c lc) body+  FVSTerm fvs db <- return $ fvSSepLTVars lc llret+  cont $ \k ->+    Decls_Cons (freeParams (fvsToLC fvs) $ \names1 ->+                boundParams lc $ \names2 ->+                skelSubst db (C.append names1 names2))+      $ nu $ \d -> k $ FVSTerm fvs (skelAppMultiNames (SDVar d) fvs)+  where+    fvsToLC :: FVList c lc -> LC lc+    fvsToLC = C.mapRAssign mbLNameToProof where+      mbLNameToProof :: MbLName c a -> LType a+      mbLNameToProof (MbLName _) = LType++-- the top-level lambda-lifting function+lambdaLift :: Term a -> Decls a+lambdaLift t = runCont (llBody MNil (emptyMb t)) $ \(FVSTerm fvs db) ->+  Decls_Base (skelSubst db (C.mapRAssign (\(MbLName mbn) -> elimEmptyMb mbn) fvs))++mbLambdaLift :: Mb c (Term a) -> Mb c (Decls a)+mbLambdaLift = fmap lambdaLift
+ src/Data/Binding/Hobbits/Examples/LambdaLifting/Examples.hs view
@@ -0,0 +1,52 @@+-- |+-- Module      : Data.Binding.Hobbits.SuperComb+-- Copyright   : (c) 2011 Edwin Westbrook, Nicolas Frisby, and Paul Brauner+--+-- License     : BSD3+--+-- Maintainer  : emw4@rice.edu+-- Stability   : experimental+-- Portability : GHC+--++module Data.Binding.Hobbits.Examples.LambdaLifting.Examples where++import Data.Binding.Hobbits.Examples.LambdaLifting.Terms+import Data.Binding.Hobbits++------------------------------------------------------------+-- examples+------------------------------------------------------------++ex1 :: Term ((b1 -> b) -> b1 -> b)+ex1 = lam (\f -> (lam $ \x -> App f x))++ex2 :: Term ((((b2 -> b1) -> b2 -> b1) -> b) -> b)+ex2 = lam (\f1 -> App f1 (lam (\f2 -> lam (\x -> App f2 x))))++ex3 :: Term (b3 -> (((b3 -> b2 -> b1) -> b2 -> b1) -> b) -> b)+ex3 = lam (\x -> lam (\f1 -> App f1 (lam (\f2 -> lam (\y -> f2 `App` x `App` y)))))++ex4+  :: Term+       (((b1 -> b) -> b2 -> b)+        -> (((b1 -> b) -> b2 -> b) -> b2 -> b1)+        -> b2+        -> b1)+ex4 = lam $ \x -> lam $ \f1 ->+      App f1 (lam $ \f2 -> lam $ \y -> f2 `App` (f1 `App` x `App` y))++ex5 :: Term (((b2 -> b1) -> b) -> (b2 -> b1) -> b)+ex5 = lam (\f1 -> lam $ \f2 -> App f1 (lam $ \x -> App f2 x))++-- lambda-lift with a free variable (use mbLambdaLift)+ex6 :: Binding (L ((b -> b) -> a)) (Term a)+ex6 = nu (\f -> App (Var f) (lam $ \x -> x))++-- lambda-lift with a free variable as part of a lambda's environment+ex7 :: Binding (L ((b2 -> b2) -> b1)) (Term ((b1 -> b) -> b))+ex7 = nu (\f -> lam $ \y -> App y $ App (Var f) (lam $ \x -> x))++-- example from paper's Section 4+exP :: Term (((b1 -> b1) -> b) -> (b1 -> b1) -> b)+exP = lam $ \f -> lam $ \g -> App f $ lam $ \x -> App g $ App g x
+ src/Data/Binding/Hobbits/Examples/LambdaLifting/Terms.hs view
@@ -0,0 +1,133 @@+{-# LANGUAGE EmptyDataDecls #-}+{-# LANGUAGE TemplateHaskell, Rank2Types, QuasiQuotes, ViewPatterns #-}+{-# LANGUAGE GADTs, KindSignatures, DataKinds #-}++-- |+-- Module      : Data.Binding.Hobbits.SuperComb+-- Copyright   : (c) 2011 Edwin Westbrook, Nicolas Frisby, and Paul Brauner+--+-- License     : BSD3+--+-- Maintainer  : emw4@rice.edu+-- Stability   : experimental+-- Portability : GHC+--++module Data.Binding.Hobbits.Examples.LambdaLifting.Terms+  (L, D,+   Term(..), lam,+   DTerm(..), Decl(..), Decls(..)+  ) where++import Data.Binding.Hobbits+import qualified Data.Type.RList as C++-- dummy datatypes for distinguishing Decl names from Lam names+data L a+data D a++-- to make a function for RAssign (for pretty)+newtype StringF x = StringF String+unStringF (StringF str) = str+++------------------------------------------------------------+-- source terms+------------------------------------------------------------++-- Term datatype; no Ds since there's no declarations yet+data Term :: * -> * where+  Var :: Name (L a) -> Term a+  Lam :: Binding (L b) (Term a) -> Term (b -> a)+  App :: Term (b -> a) -> Term b -> Term a++$(mkNuMatching [t| forall a . Term a |])++instance Show (Term a) where show = tpretty++-- helps to build terms without explicitly using nu or Var+lam :: (Term a -> Term b) -> Term (a -> b)+lam f = Lam $ nu (f . Var)++-- pretty print terms+tpretty :: Term a -> String+tpretty t = pretty' (emptyMb t) C.empty 0+  where pretty' :: Mb c (Term a) -> RAssign StringF c -> Int -> String+        pretty' [nuP| Var b |] varnames n =+            case mbNameBoundP b of+              Left pf  -> unStringF (C.get pf varnames)+              Right n -> "(free-var " ++ show n ++ ")"+        pretty' [nuP| Lam b |] varnames n =+            let x = "x" ++ show n in+            "(\\" ++ x ++ "." ++ pretty' (mbCombine b) (varnames :>: (StringF x)) (n+1) ++ ")"+        pretty' [nuP| App b1 b2 |] varnames n =+            "(" ++ pretty' b1 varnames n ++ " " ++ pretty' b2 varnames n ++ ")"++------------------------------------------------------------+-- target terms+------------------------------------------------------------++-- terms under declarations+data DTerm :: * -> * where+  TVar :: Name (L a) -> DTerm a+  TDVar :: Name (D a) -> DTerm a+  TApp :: DTerm (a -> b) -> DTerm a -> DTerm b++-- we use this type for a definiens instead of putting lambdas on the front+data Decl :: * -> * where+  Decl_One :: Binding (L a) (DTerm b) -> Decl (a -> b)+  Decl_Cons :: Binding (L a) (Decl b) -> Decl (a -> b)++-- top-level declarations with a return value+data Decls :: * -> * where+  Decls_Base :: DTerm a -> Decls a+  Decls_Cons :: Decl b -> Binding (D b) (Decls a) -> Decls a++$(mkNuMatching [t| forall a . DTerm a |])+$(mkNuMatching [t| forall a . Decl a |])+$(mkNuMatching [t| forall a . Decls a |])++instance Show (DTerm a) where show = pretty+instance Show (Decls a) where show = decls_pretty++------------------------------------------------------------+-- pretty printing+------------------------------------------------------------++-- pretty print terms+pretty :: DTerm a -> String+pretty t = mpretty (emptyMb t) C.empty++mpretty :: Mb c (DTerm a) -> RAssign StringF c -> String+mpretty [nuP| TVar b |] varnames =+    mprettyName (mbNameBoundP b) varnames+mpretty [nuP| TDVar b |] varnames =+    mprettyName (mbNameBoundP b) varnames+mpretty [nuP| TApp b1 b2 |] varnames =+    "(" ++ mpretty b1 varnames+        ++ " " ++ mpretty b2 varnames ++ ")"++mprettyName (Left pf) varnames = unStringF (C.get pf varnames)+mprettyName (Right n) varnames = "(free-var " ++ (show n) ++ ")"+        ++-- pretty print decls+decls_pretty :: Decls a -> String+decls_pretty decls =+    "let\n" ++ (mdecls_pretty (emptyMb decls) C.empty 0)++mdecls_pretty :: Mb c (Decls a) -> RAssign StringF c -> Int -> String+mdecls_pretty [nuP| Decls_Base t |] varnames n =+    "in " ++ (mpretty t varnames)+mdecls_pretty [nuP| Decls_Cons decl rest |] varnames n =+    let fname = "F" ++ show n in+    fname ++ " " ++ (mdecl_pretty decl varnames 0) ++ "\n"+    ++ mdecls_pretty (mbCombine rest) (varnames :>: (StringF fname)) (n+1)++mdecl_pretty :: Mb c (Decl a) -> RAssign StringF c -> Int -> String+mdecl_pretty [nuP| Decl_One t|] varnames n =+  let vname = "x" ++ show n in+  vname ++ " = " ++ mpretty (mbCombine t) (varnames :>: StringF vname)+mdecl_pretty [nuP| Decl_Cons d|] varnames n =+  let vname = "x" ++ show n in+  vname ++ " " ++ mdecl_pretty (mbCombine d) (varnames :>: StringF vname) (n+1)
+ src/Data/Binding/Hobbits/Internal/Closed.hs view
@@ -0,0 +1,73 @@+{-# LANGUAGE TemplateHaskell, ViewPatterns #-}++-- |+-- Module      : Data.Binding.Hobbits.Closed+-- Copyright   : (c) 2014 Edwin Westbrook, Nicolas Frisby, and Paul Brauner+--+-- License     : BSD3+--+-- Maintainer  : emw4@rice.edu+-- Stability   : experimental+-- Portability : GHC+--+-- This module defines the type @'Cl' a@ of closed objects of type+-- @a@. Note that, in order to ensure adequacy of the Hobbits+-- name-binding approach, this representation is hidden from the user,+-- and so this file should never be imported directly by the user.+--++module Data.Binding.Hobbits.Internal.Closed where++import Language.Haskell.TH (Q, Exp(..), Type(..))+import qualified Language.Haskell.TH as TH+import qualified Language.Haskell.TH.ExpandSyns as TH++import qualified Data.Generics as SYB+import qualified Language.Haskell.TH.Syntax as TH++{-| The type @Closed a@ represents a closed term of type @a@, i.e., an expression+of type @a@ with no free (Haskell) variables.  Since this cannot be checked+directly in the Haskell type system, the @Closed@ data type is hidden, and the+user can only create closed terms using Template Haskell, through the 'mkClosed'+operator. -}+newtype Closed a =+  Closed {+  -- | Extract the value of a 'Closed' object+  unClosed :: a+  }++-- | Extract the type of an 'Info' object+reifyNameType :: TH.Name -> Q Type+reifyNameType n =+  TH.reify n >>= \i ->+  case i of+    TH.VarI _ ty _ -> return ty+    _ -> fail $ "hobbits Panic -- could not reify `" ++ show n ++ "'."++-- | @mkClosed@ is used with Template Haskell quotations to create closed terms+-- of type 'Closed'. A quoted expression is closed if all of the names occuring in+-- it are either:+--+--   1) bound globally or+--   2) bound within the quotation or+--   3) also of type 'Closed'.+mkClosed :: Q Exp -> Q Exp+mkClosed e = AppE (ConE 'Closed) `fmap` e >>= SYB.everywhereM (SYB.mkM w) where+  w e@(VarE n@(TH.Name _ flav)) = case flav of+    TH.NameG {} -> return e -- bound globally+    TH.NameU {} -> return e -- bound locally within this quotation+    TH.NameL {} -> closed n >> return e -- bound locally outside this quotation+    _ -> fail $ "`mkClosed' does not allow dynamically bound names: `"+      ++ show n ++ "'."+  w e = return e++  closed n = do+    ty <- reifyNameType n+    TH.expandSyns ty >>= w ty+      where+        w _ (AppT (ConT m) _) | m == ''Closed = return ()+        w top_ty (ForallT _ _ ty') = w top_ty ty'+        w top_ty _ =+          fail $ "`mkClosed` requires non-global variables to have type `Closed'.\n\t`"+          ++ show (TH.ppr n) ++ "' does not. It's type is:\n\t `"+          ++ show (TH.ppr top_ty) ++ "'."
+ src/Data/Binding/Hobbits/Internal/Mb.hs view
@@ -0,0 +1,97 @@+{-# LANGUAGE GADTs, DeriveDataTypeable, ViewPatterns #-}+{-# LANGUAGE RankNTypes, DataKinds, PolyKinds #-}++-- |+-- Module      : Data.Binding.Hobbits.Internal.Name+-- Copyright   : (c) 2014 Edwin Westbrook, Nicolas Frisby, and Paul Brauner+--+-- License     : BSD3+--+-- Maintainer  : westbrook@kestrel.edu+-- Stability   : experimental+-- Portability : GHC+--+-- This module defines the type @'Mb' ctx a@. In order to ensure+-- adequacy of the Hobbits name-binding approach, this representation+-- is hidden, and so this file should never be imported directly by+-- the user.+--++module Data.Binding.Hobbits.Internal.Mb where++import Data.Typeable+import Data.Proxy+import Data.Type.Equality+import Data.Type.RList hiding (map)++import Data.Binding.Hobbits.Internal.Name+++{-|+  An @Mb ctx b@ is a multi-binding that binds one name for each type+  in @ctx@, where @ctx@ has the form @'RNil' ':>' t1 ':>' ... ':>' tn@.+  Internally, multi-bindings are represented either as "fresh+  functions", which are functions that quantify over all fresh names+  that have not been used before and map them to the body of the+  binding, or as "fresh pairs", which are pairs of a list of names+  that are guaranteed to be fresh along with a body. Note that fresh+  pairs must come with an 'MbTypeRepr' for the body type, to ensure+  that the names given in the pair can be relaced by fresher names.+-}+data Mb (ctx :: RList k) b+    = MkMbFun (RAssign Proxy ctx) (RAssign Name ctx -> b)+    | MkMbPair (MbTypeRepr b) (RAssign Name ctx) b+    deriving Typeable+++{-|+   This type states that it is possible to replace free names with+   fresh names in an object of type @a@. This type essentially just+   captures a representation of the type a as either a Name type, a+   multi-binding, a function type, or a (G)ADT. In order to be sure+   that only the "right" proofs are used for (G)ADTs, however, this+   type is hidden from the user, and can only be constructed with+   'mkNuMatching'.+-}++data MbTypeRepr a where+    MbTypeReprName :: MbTypeRepr (Name a)+    MbTypeReprMb :: MbTypeRepr a -> MbTypeRepr (Mb ctx a)+    MbTypeReprFun :: MbTypeRepr a -> MbTypeRepr b -> MbTypeRepr (a -> b)+    MbTypeReprData :: MbTypeReprData a -> MbTypeRepr a++data MbTypeReprData a =+    MkMbTypeReprData (forall ctx. NameRefresher -> a -> a)++{-|+  The call @mapNamesPf data ns ns' a@ replaces each occurrence of a+  free name in @a@ which is listed in @ns@ by the corresponding name+  listed in @ns'@. This is similar to the name-swapping of Nominal+  Logic, except that the swapping does not go both ways.+-}+mapNamesPf :: MbTypeRepr a -> NameRefresher -> a -> a+mapNamesPf MbTypeReprName refresher n = refreshName refresher n+mapNamesPf (MbTypeReprMb tRepr) refresher (ensureFreshFun -> (proxies, f)) =+    -- README: the fresh function created below is *guaranteed* to not+    -- be passed elements of either names1 or names2, since it should+    -- only ever be passed fresh names+    MkMbFun proxies (\ns -> mapNamesPf tRepr refresher (f ns))+mapNamesPf (MbTypeReprFun tReprIn tReprOut) refresher f =+    (mapNamesPf tReprOut refresher) . f . (mapNamesPf tReprIn refresher)+mapNamesPf (MbTypeReprData (MkMbTypeReprData mapFun)) refresher x =+    mapFun refresher x+++-- | Ensures a multi-binding is in "fresh function" form+ensureFreshFun :: Mb ctx a -> (RAssign Proxy ctx, RAssign Name ctx -> a)+ensureFreshFun (MkMbFun proxies f) = (proxies, f)+ensureFreshFun (MkMbPair tRepr ns body) =+    (mapRAssign (\_ -> Proxy) ns, \ns' ->+      mapNamesPf tRepr (mkRefresher ns ns') body)++-- | Ensures a multi-binding is in "fresh pair" form+ensureFreshPair :: Mb ctx a -> (RAssign Name ctx, a)+ensureFreshPair (MkMbPair _ ns body) = (ns, body)+ensureFreshPair (MkMbFun proxies f) =+    let ns = mapRAssign (MkName . fresh_name) proxies in+    (ns, f ns)
+ src/Data/Binding/Hobbits/Internal/Name.hs view
@@ -0,0 +1,167 @@+{-# LANGUAGE GADTs, DeriveDataTypeable, FlexibleInstances, TypeOperators #-}+{-# LANGUAGE RankNTypes, DataKinds, PolyKinds #-}++-- |+-- Module      : Data.Binding.Hobbits.Internal.Name+-- Copyright   : (c) 2014 Edwin Westbrook, Nicolas Frisby, and Paul Brauner+--+-- License     : BSD3+--+-- Maintainer  : westbrook@kestrel.edu+-- Stability   : experimental+-- Portability : GHC+--+-- This module defines the type @'Name' a@ as a wrapper around a fresh+-- integer. Note that, in order to ensure adequacy of the Hobbits+-- name-binding approach, this representation is hidden from the user,+-- and so this file should never be imported directly by the user.+--++module Data.Binding.Hobbits.Internal.Name where++import Data.List+import Data.Functor.Constant+import Data.Typeable+import Data.IntMap.Strict (IntMap)+import qualified Data.IntMap.Strict as IntMap+import Data.Type.Equality+import Unsafe.Coerce (unsafeCoerce)+import Data.IORef (IORef, newIORef, readIORef, writeIORef)+import System.IO.Unsafe (unsafePerformIO)++import Data.Type.RList+++-- | A @Name a@ is a bound name that is associated with type @a@.+newtype Name (a :: k) = MkName Int deriving (Typeable, Eq, Ord)++instance Show (Name a) where+  showsPrec _ (MkName n) = showChar '#' . shows n . showChar '#'++instance Show (RAssign Name c) where+    show names = "[" ++ (concat $ intersperse "," $ mapToList show names) ++ "]"+++-------------------------------------------------------------------------------+-- Externally visible operators+-------------------------------------------------------------------------------++{-|+  @cmpName n m@ compares names @n@ and @m@ of types @Name a@ and @Name b@,+  respectively. When they are equal, @Some e@ is returned for @e@ a proof+  of type @a :~: b@ that their types are equal. Otherwise, @None@ is returned.++  For example:++> nu $ \n -> nu $ \m -> cmpName n n   ==   nu $ \n -> nu $ \m -> Some Refl+> nu $ \n -> nu $ \m -> cmpName n m   ==   nu $ \n -> nu $ \m -> None+-}+cmpName :: Name a -> Name b -> Maybe (a :~: b)+cmpName (MkName n1) (MkName n2)+  | n1 == n2 = Just $ unsafeCoerce Refl+  | otherwise = Nothing++instance TestEquality Name where+  testEquality = cmpName++-- | Heterogeneous comparison of names, that could be at different kinds+hcmpName :: forall (a :: k1) (b :: k2). Name a -> Name b -> Maybe (a :~~: b)+hcmpName (MkName n1) (MkName n2)+  | n1 == n2 = Just $ unsafeCoerce HRefl+  | otherwise = Nothing++-- | A name refresher gives new fresh indices to names+newtype NameRefresher = NameRefresher { unNameRefresher :: IntMap Int }++-- | Apply a 'NameRefresher' to a 'Name'+refreshName :: NameRefresher -> Name a -> Name a+refreshName (NameRefresher nmap) (MkName i) =+  MkName $ IntMap.findWithDefault i i nmap++-- | Build a 'NameRefresher' that maps one sequence of names to another+mkRefresher :: forall (ctx :: RList k) .+               RAssign Name ctx -> RAssign Name ctx -> NameRefresher+mkRefresher ns1 ns2 =+  NameRefresher $ IntMap.fromList $ toList $+  map2 (\(MkName i) (MkName j) -> Constant (i,j)) ns1 ns2++-- | Extend a 'NameRefresher' with one more name mapping+extRefresher :: forall (a :: k). NameRefresher -> Name a -> Name a ->+                NameRefresher+extRefresher (NameRefresher nmap) (MkName n1) (MkName n2) =+  NameRefresher $+  IntMap.insertWith (\_ _ -> error "Hobbit name already in NameRefresher!")+  n1 n2 nmap+++-------------------------------------------------------------------------------+-- Hidden, unsafe operators+-------------------------------------------------------------------------------+++-- building an arbitrary InCtx proof with a given length+-- (this is used internally in HobbitLib)++data ExMember where ExMember :: Member c a -> ExMember++-- creating some Member proof of length i+memberFromLen :: Int -> ExMember+memberFromLen 0 = ExMember Member_Base+memberFromLen n = case memberFromLen (n - 1) of+  ExMember mem -> ExMember (Member_Step mem)++-- unsafely creating a *specific* member proof from length i;+-- this is for when we know the ith element of c must be type a+unsafeLookupC :: Int -> Member c a+unsafeLookupC n = case memberFromLen n of+  ExMember mem -> unsafeCoerce mem+++-- building a proxy for each type in some unknown context+data ExProxy where ExProxy :: RAssign Proxy ctx -> ExProxy+proxyFromLen :: Int -> ExProxy+proxyFromLen 0 = ExProxy MNil+proxyFromLen n = case proxyFromLen (n - 1) of+                   ExProxy proxy -> ExProxy (proxy :>: Proxy)++-- -- unsafely building a proxy for each type in ctx from the length n+-- -- of ctx; this is only safe when we know the length of ctx = n+-- unsafeProxyFromLen :: Int -> MapC Proxy ctx+-- unsafeProxyFromLen n = case proxyFromLen n of+--                          ExProxy proxy -> unsafeCoerce proxy++-- -- unsafely convert a list of Ints, used to represent names, to+-- -- names of certain, given types; note that the first name in the+-- -- list becomes the last name in the output, with the same reversal+-- -- used in the Mb representation (see, e.g., mbCombine)+-- unsafeNamesFromInts :: [Int] -> MapC Name ctx+-- unsafeNamesFromInts [] = unsafeCoerce Nil+-- unsafeNamesFromInts (x:xs) =+--     unsafeCoerce $ unsafeNamesFromInts xs :> MkName x++-------------------------------------------------------------------------------+-- encapsulated impurity+-------------------------------------------------------------------------------++-- README: we *cannot* inline counter, because we want all uses+-- of counter to be the same IORef+counter :: IORef Int+{-# NOINLINE counter #-}+counter = unsafePerformIO (newIORef 0)++-- README: fresh_name takes a dummy argument that is used in a dummy+-- way to avoid let-floating its body (and thus getting a fresh name+-- exactly once)+-- README: it *is* ok to inline fresh_name because we don't care in+-- what order fresh names are created+fresh_name :: a -> Int+fresh_name a = unsafePerformIO $ do +    dummyRef <- newIORef a+    x <- readIORef counter+    writeIORef counter (x+1)+    return x++-- -- make one fresh name for each name in a given input list+-- fresh_names :: MapC Name ctx -> MapC Name ctx+-- fresh_names Nil = Nil+-- fresh_names (names :> n) = fresh_names names :> MkName (fresh_name n)
+ src/Data/Binding/Hobbits/Internal/Utilities.hs view
@@ -0,0 +1,13 @@+{-# LANGUAGE Rank2Types #-}++module Data.Binding.Hobbits.Internal.Utilities where++import qualified Data.Generics as SYB++++everywhereButM :: Monad m =>+  SYB.GenericQ Bool -> SYB.GenericM m -> SYB.GenericM m+everywhereButM q f x+  | q x       = return x+  | otherwise = (SYB.gmapM (everywhereButM q f) x) >>= f
+ src/Data/Binding/Hobbits/Liftable.hs view
@@ -0,0 +1,154 @@+{-# LANGUAGE GADTs, TypeOperators, FlexibleInstances, TemplateHaskell #-}+{-# LANGUAGE ViewPatterns, QuasiQuotes, DataKinds, PolyKinds #-}++-- |+-- Module      : Data.Binding.Hobbits.Mb+-- Copyright   : (c) 2014 Edwin Westbrook+--+-- License     : BSD3+--+-- Maintainer  : emw4@rice.edu+-- Stability   : experimental+-- Portability : GHC+--+-- This module defines the type-class Liftable for lifting+-- non-binding-related data out of name-bindings. Note that this code+-- is not "trusted", i.e., it is not part of the name-binding+-- abstraction: instead, it is all written using the primitives+-- exported by the Mb++module Data.Binding.Hobbits.Liftable where++import Data.Type.RList+import Data.Binding.Hobbits.Mb+import Data.Binding.Hobbits.Internal.Mb+import Data.Binding.Hobbits.QQ+import Data.Binding.Hobbits.Closed+import Data.Binding.Hobbits.NuMatching+import Data.Binding.Hobbits.NuMatchingInstances++import Data.Ratio+import Data.Proxy+import Numeric.Natural+import Data.Type.Equality+++{-|+  The class @Liftable a@ gives a \"lifting function\" for a, which can+  take any data of type @a@ out of a multi-binding of type @'Mb' ctx a@.+-}+class NuMatching a => Liftable a where+    mbLift :: Mb ctx a -> a++-------------------------------------------------------------------------------+-- * Lifting instances that must be defined inside the library abstraction boundary+-------------------------------------------------------------------------------++instance Liftable Char where+    mbLift (ensureFreshPair -> (_, c)) = c++instance Liftable Int where+    mbLift (ensureFreshPair -> (_, i)) = i++instance Liftable Integer where+    mbLift (ensureFreshPair -> (_, i)) = i++instance Liftable (Closed a) where+    mbLift (ensureFreshPair -> (_, c)) = c++instance Liftable Natural where+    mbLift (ensureFreshPair -> (_, i)) = i+++-------------------------------------------------------------------------------+-- * Lifting instances and related functions that could be defined outside the library+-------------------------------------------------------------------------------++-- README: this requires overlapping instances, because it clashes+-- with Liftable2, but this instance is better because it does not+-- require c nor a to be liftable+instance Liftable (Member c a) where+    mbLift [nuP| Member_Base |] = Member_Base+    mbLift [nuP| Member_Step m |] = Member_Step (mbLift m)++-- | Lift a list (but not its elements) out of a multi-binding+mbList :: NuMatching a => Mb c [a] -> [Mb c a]+mbList [nuP| [] |] = []+mbList [nuP| x : xs |] = x : mbList xs++instance (Integral a, NuMatching a) => NuMatching (Ratio a) where+  nuMatchingProof =+    isoMbTypeRepr (\r -> (numerator r, denominator r)) (\(n,d) -> n%d)+instance (Integral a, Liftable a) => Liftable (Ratio a) where+  mbLift mb_r =+    (\(n,d) -> n%d) $ mbLift $ fmap (\r -> (numerator r, denominator r)) mb_r++instance Liftable a => Liftable [a] where+    mbLift [nuP| [] |] = []+    mbLift [nuP| x : xs |] = (mbLift x) : (mbLift xs)++instance Liftable () where+    mbLift [nuP| () |] = ()++instance (Liftable a, Liftable b) => Liftable (a,b) where+    mbLift [nuP| (x,y) |] = (mbLift x, mbLift y)++instance Liftable Bool where+  mbLift [nuP| True |] = True+  mbLift [nuP| False |] = False++instance Liftable a => Liftable (Maybe a) where+  mbLift [nuP| Nothing |] = Nothing+  mbLift [nuP| Just mb_a |] = Just $ mbLift mb_a++instance (Liftable a, Liftable b) => Liftable (Either a b) where+  mbLift [nuP| Left mb_a |] = Left $ mbLift mb_a+  mbLift [nuP| Right mb_b |] = Right $ mbLift mb_b++instance Liftable (a :~: b) where+  mbLift [nuP| Refl |] = Refl++instance Liftable (Proxy (a :: k)) where+  mbLift [nuP| Proxy |] = Proxy++-- Ideally this would be in the Mb module, but that ends up producing a circular+-- include due to needing `mbLift`+instance Eq a => Eq (Mb ctx a) where+  mb1 == mb2 =+    mbLift $ nuMultiWithElim (\_ (_ :>: a1 :>: a2) ->+                               a1 == a2) (MNil :>: mb1 :>: mb2)++++-- README: these lead to overlapping instances...++{-++{-|+  The class @Liftable1 f@ gives a lifting function for each type @f a@+  when @a@ itself is @Liftable@.+-}+class Liftable1 f where+    mbLift1 :: Liftable a => Mb ctx (f a) -> f a++instance (Liftable1 f, Liftable a) => Liftable (f a) where+    mbLift = mbLift1++instance Liftable1 [] where+    mbLift1 [nuP| [] |] = []+    mbLift1 [nuP| x : xs |] = (mbLift x) : (mbLift1 xs)++{-|+  The class @Liftable2 f@ gives a lifting function for each type @f a b@+  when @a@ and @b@ are @Liftable@.+-}+class Liftable2 f where+    mbLift2 :: (Liftable a, Liftable b) => Mb ctx (f a b) -> f a b++instance Liftable2 (,) where+    mbLift2 [nuP| (x,y) |] = (mbLift x, mbLift y)++instance (Liftable2 f, Liftable a) => Liftable1 (f a) where+    mbLift1 = mbLift2++-}
+ src/Data/Binding/Hobbits/Mb.hs view
@@ -0,0 +1,324 @@+{-# LANGUAGE GADTs, TypeOperators, FlexibleInstances, ViewPatterns, DataKinds #-}+{-# LANGUAGE RankNTypes, PolyKinds #-}++-- |+-- Module      : Data.Binding.Hobbits.Mb+-- Copyright   : (c) 2011 Edwin Westbrook, Nicolas Frisby, and Paul Brauner+--+-- License     : BSD3+--+-- Maintainer  : emw4@rice.edu+-- Stability   : experimental+-- Portability : GHC+--+-- This module defines multi-bindings as the type 'Mb', as well as a number of+-- operations on multi-bindings. See the paper E. Westbrook, N. Frisby,+-- P. Brauner, \"Hobbits for Haskell: A Library for Higher-Order Encodings in+-- Functional Programming Languages\" for more information.++module Data.Binding.Hobbits.Mb (+  -- * Abstract types+  Name(),      -- hides Name implementation+  Binding(),   -- hides Binding implementation+  Mb(),        -- hides MultiBind implementation+  -- * Multi-binding constructors+  nu, nuMulti, nus, emptyMb, extMb, extMbMulti,+  -- * Queries on names+  cmpName, hcmpName, mbNameBoundP, mbCmpName,+  -- * Operations on multi-bindings+  elimEmptyMb, mbCombine, mbSeparate, mbToProxy, mbSwap, mbPure, mbApply,+  mbMap2,+  -- * Eliminators for multi-bindings+  nuMultiWithElim, nuWithElim, nuMultiWithElim1, nuWithElim1+) where++import Control.Applicative+import Control.Monad.Identity++import Data.Type.Equality ((:~:)(..))+import Data.Proxy (Proxy(..))++import Unsafe.Coerce (unsafeCoerce)++import Data.Type.RList++import Data.Binding.Hobbits.Internal.Name+import Data.Binding.Hobbits.Internal.Mb+--import qualified Data.Binding.Hobbits.Internal as I++-------------------------------------------------------------------------------+-- creating bindings+-------------------------------------------------------------------------------++-- | A @Binding@ is simply a multi-binding that binds one name+type Binding (a :: k) = Mb (RNil :> a)++-- note: we reverse l to show the inner-most bindings last+instance Show a => Show (Mb c a) where+  showsPrec p (ensureFreshPair -> (names, b)) = showParen (p > 10) $+    showChar '#' . shows names . showChar '.' . shows b++{-|+  @nu f@ creates a binding which binds a fresh name @n@ and whose+  body is the result of @f n@.+-}+nu :: forall (a :: k1) (b :: *) . (Name a -> b) -> Binding a b+nu f = MkMbFun (MNil :>: Proxy) (\(MNil :>: n) -> f n)++{-|+  The expression @nuMulti p f@ creates a multi-binding of zero or more+  names, one for each element of the vector @p@. The bound names are+  passed the names to @f@, which returns the body of the+  multi-binding.  The argument @p@, of type @'RAssign' f ctx@, acts as a+  \"phantom\" argument, used to reify the list of types @ctx@ at the+  term level; thus it is unimportant what the type function @f@ is.+-}+nuMulti :: RAssign f ctx -> (RAssign Name ctx -> b) -> Mb ctx b+nuMulti proxies f = MkMbFun (mapRAssign (const Proxy) proxies) f++-- | @nus = nuMulti@+nus x = nuMulti x++-- | Extend the context of a name-binding by adding a single type+extMb :: Mb ctx a -> Mb (ctx :> tp) a+extMb = mbCombine . fmap (nu . const)++-- | Extend the context of a name-binding with multiple types+extMbMulti :: RAssign f ctx2 -> Mb ctx1 a -> Mb (ctx1 :++: ctx2) a+extMbMulti ns mb = mbCombine $ fmap (nuMulti ns . const) mb+++-------------------------------------------------------------------------------+-- Queries on Names+-------------------------------------------------------------------------------++{-|+  Checks if a name is bound in a multi-binding, returning @Left mem@+  when the name is bound, where @mem@ is a proof that the type of the+  name is in the type list for the multi-binding, and returning+  @Right n@ when the name is not bound, where @n@ is the name.++  For example:++> nu $ \n -> mbNameBoundP (nu $ \m -> m)  ==  nu $ \n -> Left Member_Base+> nu $ \n -> mbNameBoundP (nu $ \m -> n)  ==  nu $ \n -> Right n+-}+mbNameBoundP :: forall (a :: k1) (ctx :: RList k2).+                Mb ctx (Name a) -> Either (Member ctx a) (Name a)+mbNameBoundP (ensureFreshPair -> (names, n)) = helper names n where+    helper :: RAssign Name c -> Name a -> Either (Member c a) (Name a)+    helper MNil n = Right n+    helper (names :>: (MkName i)) (MkName j)+      | i == j =+        unsafeCoerce $ Left Member_Base+    helper (names :>: _) n =+      case helper names n of+        Left memb -> Left (Member_Step memb)+        Right n -> Right n+-- old implementation with lists+{-+case elemIndex n names of+  Nothing -> Right (MkName n)+  Just i -> Left (I.unsafeLookupC i)+-}+++{-|+  Compares two names inside bindings, taking alpha-equivalence into+  account; i.e., if both are the @i@th name, or both are the same name+  not bound in their respective multi-bindings, then they compare as+  equal. The return values are the same as for 'cmpName', so that+  @Some Refl@ is returned when the names are equal and @Nothing@ is+  returned when they are not.+-}+mbCmpName :: forall (a :: k1) (b :: k1) (c :: RList k2).+             Mb c (Name a) -> Mb c (Name b) -> Maybe (a :~: b)+mbCmpName (ensureFreshPair -> (names, n1)) (ensureFreshFun -> (_, f2)) =+  cmpName n1 (f2 names)+++-------------------------------------------------------------------------------+-- Operations on multi-bindings+-------------------------------------------------------------------------------++-- | Creates an empty binding that binds 0 names.+emptyMb :: a -> Mb RNil a+emptyMb body = MkMbFun MNil (\_ -> body)++{-|+  Eliminates an empty binding, returning its body. Note that+  @elimEmptyMb@ is the inverse of @emptyMb@.+-}+elimEmptyMb :: Mb RNil a -> a+elimEmptyMb (ensureFreshPair -> (_, body)) = body+++-- Extract the proxy objects from an Mb inside of a fresh function+freshFunctionProxies :: RAssign Proxy ctx1 -> (RAssign Name ctx1 -> Mb ctx2 a) ->+                        RAssign Proxy ctx2+freshFunctionProxies proxies1 f =+    case f (mapRAssign (const $ MkName 0) proxies1) of+      MkMbFun proxies2 _ -> proxies2+      MkMbPair _ ns _ -> mapRAssign (const Proxy) ns+++-- README: inner-most bindings come FIRST+-- | Combines a binding inside another binding into a single binding.+mbCombine :: forall (c1 :: RList k) (c2 :: RList k) a b.+             Mb c1 (Mb c2 b) -> Mb (c1 :++: c2) b+mbCombine (MkMbPair tRepr1 l1 (MkMbPair tRepr2 l2 b)) =+  MkMbPair tRepr2 (append l1 l2) b+mbCombine (ensureFreshFun -> (proxies1, f1)) =+    -- README: we pass in Names with integer value 0 here in order to+    -- get out the proxies for the inner-most bindings; this is "safe"+    -- because these proxies should never depend on the names+    -- themselves+    let proxies2 = freshFunctionProxies proxies1 f1 in+    MkMbFun+    (append proxies1 proxies2)+    (\ns ->+         let (ns1, ns2) = split Proxy proxies2 ns in+         let (_, f2) = ensureFreshFun (f1 ns1) in+         f2 ns2)+++{-|+  Separates a binding into two nested bindings. The first argument, of+  type @'RAssign' any c2@, is a \"phantom\" argument to indicate how+  the context @c@ should be split.+-}+mbSeparate :: forall (ctx1 :: RList k) (ctx2 :: RList k) (any :: k -> *) a.+              RAssign any ctx2 -> Mb (ctx1 :++: ctx2) a ->+              Mb ctx1 (Mb ctx2 a)+mbSeparate c2 (MkMbPair tRepr ns a) =+    MkMbPair (MbTypeReprMb tRepr) ns1 (MkMbPair tRepr ns2 a) where+        (ns1, ns2) = split Proxy c2 ns+mbSeparate c2 (MkMbFun proxies f) =+    MkMbFun proxies1 (\ns1 -> MkMbFun proxies2 (\ns2 -> f (append ns1 ns2)))+        where+          (proxies1, proxies2) = split Proxy c2 proxies+++-- | Returns a proxy object that enumerates all the types in ctx.+mbToProxy :: forall (ctx :: RList k) (a :: *) .+             Mb ctx a -> RAssign Proxy ctx+mbToProxy (MkMbFun proxies _) = proxies+mbToProxy (MkMbPair _ ns _) = mapRAssign (\_ -> Proxy) ns+++{-|+  Take a multi-binding inside another multi-binding and move the+  outer binding inside the ineer one.+-}+mbSwap :: Mb ctx1 (Mb ctx2 a) -> Mb ctx2 (Mb ctx1 a)+mbSwap (ensureFreshFun -> (proxies1, f1)) =+    let proxies2 = freshFunctionProxies proxies1 f1 in+    MkMbFun proxies2+      (\ns2 ->+         MkMbFun proxies1+         (\ns1 ->+            snd (ensureFreshFun (f1 ns1)) ns2))++-- | Put a value inside a multi-binding+mbPure :: RAssign f ctx -> a -> Mb ctx a+mbPure prxs = nuMulti prxs . const++{-|+  Applies a function in a multi-binding to an argument in a+  multi-binding that binds the same number and types of names.+-}+mbApply :: Mb ctx (a -> b) -> Mb ctx a -> Mb ctx b+mbApply (ensureFreshFun -> (proxies, f_fun)) (ensureFreshFun -> (_, f_arg)) =+  MkMbFun proxies (\ns -> f_fun ns $ f_arg ns)+++-- | Lift a binary function function to `Mb`s+mbMap2 :: (a -> b -> c) -> Mb ctx a -> Mb ctx b -> Mb ctx c+mbMap2 f mb1 mb2 = fmap f mb1 `mbApply` mb2++-------------------------------------------------------------------------------+-- Functor and Applicative instances+-------------------------------------------------------------------------------++instance Functor (Mb ctx) where+    fmap f mbArg =+        mbApply (nuMulti (mbToProxy mbArg) (\_ -> f)) mbArg++instance TypeCtx ctx => Applicative (Mb ctx) where+    pure x = nuMulti typeCtxProxies (const x)+    (<*>) = mbApply+++-------------------------------------------------------------------------------+-- Eliminators for multi-bindings+-------------------------------------------------------------------------------++-- FIXME: add more examples!!+{-|++  asdfasdf++  The expression @nuWithElimMulti args f@ takes a sequence @args@ of one or more+  multi-bindings (it is a runtime error to pass an empty sequence of arguments),+  each of type @Mb ctx ai@ for the same type context @ctx@ of bound names, and a+  function @f@ and does the following:++  * Creates a multi-binding that binds names @n1,...,nn@, one name for+    each type in @ctx@;++  * Substitutes the names @n1,...,nn@ for the names bound by each+    argument in the @args@ sequence, yielding the bodies of the @args@+    (using the new name @n@); and then++  * Passes the sequence @n1,...,nn@ along with the result of+    substituting into @args@ to the function @f@, which then returns+    the value for the newly created binding.++  For example, here is an alternate way to implement 'mbApply':++> mbApply' :: Mb ctx (a -> b) -> Mb ctx a -> Mb ctx b+> mbApply' f a =+>     nuWithElimMulti ('MNil' :>: f :>: a)+>                     (\_ ('MNil' :>: 'Identity' f' :>: 'Identity' a') -> f' a')+-}+nuMultiWithElim :: (RAssign Name ctx -> RAssign Identity args -> b) ->+                   RAssign (Mb ctx) args -> Mb ctx b+nuMultiWithElim f args =+  let proxies =+        case args of+          MNil -> error "nuMultiWithElim"+          (_ :>: arg1) -> mbToProxy arg1 in+  MkMbFun proxies+          (\ns ->+            f ns $ mapRAssign (\arg ->+                                Identity $ snd (ensureFreshFun arg) ns) args)+++{-|+  Similar to 'nuMultiWithElim' but binds only one name. Note that the argument+  list here is allowed to be empty.+-}+nuWithElim :: (Name a -> RAssign Identity args -> b) ->+              RAssign (Mb (RNil :> a)) args ->+              Binding a b+nuWithElim f MNil = nu $ \n -> f n MNil+nuWithElim f args =+    nuMultiWithElim (\(MNil :>: n) -> f n) args+++{-|+  Similar to 'nuMultiWithElim' but takes only one argument+-}+nuMultiWithElim1 :: (RAssign Name ctx -> arg -> b) -> Mb ctx arg -> Mb ctx b+nuMultiWithElim1 f arg =+    nuMultiWithElim (\names (MNil :>: Identity arg) -> f names arg)+    (MNil :>: arg)+++{-|+  Similar to 'nuMultiWithElim' but takes only one argument that binds+  a single name.+-}+nuWithElim1 :: (Name a -> arg -> b) -> Binding a arg -> Binding a b+nuWithElim1 f arg =+  nuWithElim (\n (MNil :>: Identity arg) -> f n arg) (MNil :>: arg)
+ src/Data/Binding/Hobbits/MonadBind.hs view
@@ -0,0 +1,102 @@+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE PolyKinds #-}+{-# LANGUAGE QuasiQuotes #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE ViewPatterns #-}++-- |+-- Module      : Data.Binding.Hobbits.MonadBind+-- Copyright   : (c) 2020 Edwin Westbrook+--+-- License     : BSD3+--+-- Maintainer  : westbrook@galois.com+-- Stability   : experimental+-- Portability : GHC+--+-- This module defines monads that are compatible with the notion of+-- name-binding, where a monad is compatible with name-binding iff it can+-- intuitively run computations that are inside name-bindings. More formally, a+-- /binding monad/ is a monad with an operation 'mbM' that commutes name-binding+-- with the monadic operations, meaning:+--+-- > 'mbM' ('nuMulti' $ \ns -> 'return' a) == 'return' ('nuMulti' $ \ns -> a)+-- > 'mbM' ('nuMulti' $ \ns -> m >>= f)+-- >   == 'mbM' ('nuMulti' $ \ns -> m) >>= \mb_x ->+-- >      'mbM' (('nuMulti' $ \ns x -> f x) `'mbApply'` mb_x)++module Data.Binding.Hobbits.MonadBind (MonadBind(..), MonadStrongBind(..)) where++import Data.Binding.Hobbits.Closed+import Data.Binding.Hobbits.Liftable (mbLift)+import Data.Binding.Hobbits.Mb+import Data.Binding.Hobbits.NuMatching+import Data.Binding.Hobbits.QQ++import Control.Monad.Identity (Identity(..))+import Control.Monad.Reader (ReaderT(..))+import Control.Monad.State (StateT(..), get, lift, put, runStateT)++-- | The class of name-binding monads+class Monad m => MonadBind m where+  mbM :: NuMatching a => Mb ctx (m a) -> m (Mb ctx a)++-- | Bind a name inside a computation and return the name-binding whose body was+-- returned by the computation+nuM :: (MonadBind m, NuMatching b) => (Name a -> m b) -> m (Binding a b)+nuM = mbM . nu++instance MonadBind Identity where+  mbM = Identity . fmap runIdentity++instance MonadBind Maybe where+  mbM [nuP| Just x |] = return x+  mbM [nuP| Nothing |] = Nothing++instance MonadBind m => MonadBind (ReaderT r m) where+  mbM mb = ReaderT $ \r -> mbM $ fmap (flip runReaderT r) mb++-- | A version of 'MonadBind' that does not require a 'NuMatching' instance on+-- the element type of the multi-binding in the monad+class MonadBind m => MonadStrongBind m where+  strongMbM :: Mb ctx (m a) -> m (Mb ctx a)++instance MonadStrongBind Identity where+  strongMbM = Identity . fmap runIdentity++instance MonadStrongBind m => MonadStrongBind (ReaderT r m) where+  strongMbM mb = ReaderT $ \r -> strongMbM $ fmap (flip runReaderT r) mb++-- | State types that can incorporate name-bindings+class NuMatching s => BindState s where+  bindState :: Mb ctx s -> s++instance BindState (Closed s) where+  bindState = mbLift++instance (MonadBind m, BindState s) => MonadBind (StateT s m) where+  mbM mb_m = StateT $ \s ->+    mbM (fmap (\m -> runStateT m s) mb_m) >>= \mb_as ->+    return (fmap fst mb_as, bindState (fmap snd mb_as))++instance (MonadStrongBind m, BindState s) => MonadStrongBind (StateT s m) where+  strongMbM mb_m = StateT $ \s ->+    strongMbM (fmap (\m -> runStateT m s) mb_m) >>= \mb_as ->+    return (fmap fst mb_as, bindState (fmap snd mb_as))+++-- | A monad whose effects are closed+class Monad m => MonadClosed m where+  closedM :: Closed (m a) -> m (Closed a)++instance MonadClosed Identity where+  closedM = Identity . clApply $(mkClosed [| runIdentity |])++instance (MonadClosed m, Closable s) => MonadClosed (StateT s m) where+  closedM clm =+    do s <- get+       cl_a_s <- lift $ closedM ($(mkClosed [| runStateT |]) `clApply` clm+                                 `clApply` toClosed s)+       put (snd $ unClosed cl_a_s)+       return ($(mkClosed [| fst |]) `clApply` cl_a_s)
+ src/Data/Binding/Hobbits/NameMap.hs view
@@ -0,0 +1,197 @@+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE KindSignatures #-}+{-# LANGUAGE PolyKinds #-}+{-# LANGUAGE QuasiQuotes #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE ViewPatterns #-}++-- |+-- Module      : Data.Binding.Hobbits.Mb+-- Copyright   : (c) 2019 Edwin Westbrook+--+-- License     : BSD3+--+-- Maintainer  : westbrook@galois.com+-- Stability   : experimental+-- Portability : GHC+--+-- Implements mappings from 'Name's to some associated data, using+-- 'Data.IntMap.Strict'. Note that these mappings are strict.+--+-- All of the functions in this module operate in an identical manner as those+-- of the same name in the 'Data.IntMap.Strict' module.++module Data.Binding.Hobbits.NameMap (+  NameMap(), NameAndElem(..)+  , empty, singleton, fromList+  , insert, delete, adjust, update, alter+  , lookup, (!), member, null, size+  , union, difference, (\\), intersection+  , map, foldr, foldl+  , assocs+  , liftNameMap+  ) where++import Prelude hiding (lookup, null, map, foldr, foldl)+import qualified Prelude as Prelude (map)+import Data.IntMap.Strict (IntMap)+import qualified Data.IntMap.Strict as IntMap+import Unsafe.Coerce++import Data.Binding.Hobbits.Internal.Name+import Data.Binding.Hobbits.Mb+import Data.Binding.Hobbits.NuMatching+import Data.Binding.Hobbits.NuMatchingInstances+import Data.Binding.Hobbits.QQ++-- | An element of a 'NameMap', where the name type @a@ is existentially+-- quantified+data NMElem (f :: k -> *) where+  NMElem :: f a -> NMElem f++-- | Coerce an @'NMElem' f@ to an @f a@ for a specific type @a@. This assumes we+-- know that this is the proper type to coerce it to, i.e., it is unsafe.+coerceNMElem :: NMElem f -> f a+coerceNMElem (NMElem x) = unsafeCoerce x++-- | A heterogeneous map from 'Name's of arbitrary type @a@ to elements of @f a@+newtype NameMap (f :: k -> *) =+  NameMap { unNameMap :: IntMap (NMElem f) }++-- | Internal-only helper function for mapping a unary function on 'IntMap's to+-- a 'NameMap'+mapNMap1 :: (IntMap (NMElem f) -> IntMap (NMElem f)) -> NameMap f -> NameMap f+mapNMap1 f (NameMap m) = NameMap $ f m++-- | Internal-only helper function for mapping a binary function on 'IntMap's to+-- 'NameMap's+mapNMap2 :: (IntMap (NMElem f) -> IntMap (NMElem f) -> IntMap (NMElem f)) ->+            NameMap f -> NameMap f -> NameMap f+mapNMap2 f (NameMap m1) (NameMap m2) = NameMap $ f m1 m2++-- | The empty 'NameMap'+empty :: NameMap f+empty = NameMap IntMap.empty++-- | The singleton 'NameMap' with precisely one 'Name' and corresponding value+singleton :: Name a -> f a -> NameMap f+singleton (MkName i) x = NameMap $ IntMap.singleton i $ NMElem x++-- | A pair of a 'Name' of some type @a@ along with an element of type @f a@+data NameAndElem f where+  NameAndElem :: Name a -> f a -> NameAndElem f++-- | Build a 'NameMap' from a list of pairs of names and values they map to+fromList :: [NameAndElem f] -> NameMap f+fromList =+  NameMap . IntMap.fromList .+  Prelude.map (\ne ->+                case ne of+                  NameAndElem (MkName i) f -> (i, NMElem f))++-- | Insert a 'Name' and a value it maps to into a 'NameMap'+insert :: Name a -> f a -> NameMap f -> NameMap f+insert (MkName i) f = mapNMap1 $ IntMap.insert i (NMElem f)++-- | Delete a 'Name' and the value it maps to from a 'NameMap'+delete :: Name a -> NameMap f -> NameMap f+delete (MkName i) = mapNMap1 $ IntMap.delete i++-- | Apply a function to the value mapped to by a 'Name'+adjust :: (f a -> f a) -> Name a -> NameMap f -> NameMap f+adjust f (MkName i) = mapNMap1 $ IntMap.adjust (NMElem . f . coerceNMElem) i++-- | Update the value mapped to by a 'Name', possibly deleting it+update :: (f a -> Maybe (f a)) -> Name a -> NameMap f -> NameMap f+update f (MkName i) = mapNMap1 $ IntMap.update (fmap NMElem . f . coerceNMElem) i++-- | Apply a function to the optional value associated with a 'Name', where+-- 'Nothing' represents the 'Name' not being present in the 'NameMap'+alter :: (Maybe (f a) -> Maybe (f a)) -> Name a -> NameMap f -> NameMap f+alter f (MkName i) =+  mapNMap1 $ IntMap.alter (fmap NMElem . f . fmap coerceNMElem) i++-- | Look up the value associated with a 'Name', returning 'Nothing' if there is+-- none+lookup :: Name a -> NameMap f -> Maybe (f a)+lookup (MkName i) (NameMap m) = fmap coerceNMElem $ IntMap.lookup i m++-- | Synonym for 'lookup' with the argument order reversed+(!) :: NameMap f -> Name a -> f a+(NameMap m) ! (MkName i) = coerceNMElem $ m IntMap.! i++-- | Test if a 'Name' has a value in a 'NameMap'+member :: Name a -> NameMap f -> Bool+member (MkName i) (NameMap m) = IntMap.member i m++-- | Test if a 'NameMap' is empty+null :: NameMap f -> Bool+null (NameMap m) = IntMap.null m++-- | Return the number of 'Name's in a 'NameMap'+size :: NameMap f -> Int+size (NameMap m) = IntMap.size m++-- | Union two 'NameMap's+union :: NameMap f -> NameMap f -> NameMap f+union = mapNMap2 IntMap.union++-- | Remove all bindings in the first 'NameMap' for 'Name's in the second+difference :: NameMap f -> NameMap f -> NameMap f+difference = mapNMap2 IntMap.difference++-- | Infix synonym for 'difference'+(\\) :: NameMap f -> NameMap f -> NameMap f+(\\) = difference++-- | Intersect two 'NameMap's+intersection :: NameMap f -> NameMap f -> NameMap f+intersection = mapNMap2 IntMap.intersection++-- | Map a function across the values associated with each 'Name'+map :: (forall a. f a -> g a) -> NameMap f -> NameMap g+map f (NameMap m) =+  NameMap $ IntMap.map (\e -> case e of+                           NMElem x -> NMElem $ f x) m++-- | Perform a right fold across all values in a 'NameMap'+foldr :: (forall a. f a -> b -> b) -> b -> NameMap f -> b+foldr f b (NameMap m) =+  IntMap.foldr (\e -> case e of+                   NMElem x -> f x) b m++-- | Perform a left fold across all values in a 'NameMap'+foldl :: (forall b. a -> f b -> a) -> a -> NameMap f -> a+foldl f a (NameMap m) =+  IntMap.foldl (\a e -> case e of+                   NMElem x -> f a x) a m++-- | Return all 'Name's in a 'NameMap' with their associated values+assocs :: NameMap f -> [NameAndElem f]+assocs (NameMap m) =+  Prelude.map (\(i, e) -> case e of+                  NMElem f -> NameAndElem (MkName i) f) $+  IntMap.assocs m++$(mkNuMatching [t| forall f. NuMatchingAny1 f => NameAndElem f |])++-- | Lift a 'NameMap' out of a name-binding using a "partial lifting function"+-- that can lift some values in the 'NameMap' out of the binding. The resulting+-- 'NameMap' contains those names and associated values where the names were not+-- bound by the name-binding and the partial lifting function was able to lift+-- their associated values.+liftNameMap :: forall ctx f a. NuMatchingAny1 f =>+               (forall a. Mb ctx (f a) -> Maybe (f a)) ->+               Mb ctx (NameMap f) -> NameMap f+liftNameMap lifter = helper . fmap assocs where+  helper :: Mb ctx [NameAndElem f] -> NameMap f+  helper [nuP| [] |] = empty+  helper [nuP| (NameAndElem mb_n mb_f):mb_elems |]+    | Right n <- mbNameBoundP mb_n+    , Just f <- lifter mb_f+    = insert n f (helper mb_elems)+  helper [nuP| _:mb_elems |] = helper mb_elems
+ src/Data/Binding/Hobbits/NameSet.hs view
@@ -0,0 +1,135 @@+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE KindSignatures #-}+{-# LANGUAGE PolyKinds #-}+{-# LANGUAGE QuasiQuotes #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE ViewPatterns #-}+{-# LANGUAGE PatternGuards #-}++-- |+-- Module      : Data.Binding.Hobbits.NameSet+-- Copyright   : (c) 2020 Edwin Westbrook+--+-- License     : BSD3+--+-- Maintainer  : westbrook@galois.com+-- Stability   : experimental+-- Portability : GHC+--+-- Implements sets of 'Name's using 'Data.IntSet.Strict'. Note that these+-- mappings are strict.++module Data.Binding.Hobbits.NameSet (+  NameSet(), SomeName(..)+  , empty, singleton, fromList, toList+  , insert, delete, member, null, size+  , union, unions, difference, (\\), intersection+  , map, foldr, foldl+  , liftNameSet+  ) where++import Prelude hiding (lookup, null, map, foldr, foldl)+import qualified Prelude as Prelude (map)+import Data.Maybe+import Data.IntSet (IntSet)+import qualified Data.IntSet as IntSet+import Data.Kind+import qualified Data.Foldable as Foldable++import Data.Binding.Hobbits.Internal.Name+import Data.Binding.Hobbits.Mb+import Data.Binding.Hobbits.NuMatching+import Data.Binding.Hobbits.QQ+import Data.Binding.Hobbits.Liftable++-- | A set of 'Name's whose types all have kind @k@+newtype NameSet k = NameSet { unNameSet :: IntSet }++-- | A 'Name' of some unknown type of kind @k@+data SomeName k = forall (a :: k). SomeName (Name a)++$(mkNuMatching [t| forall k. SomeName k |])++-- | The empty 'NameSet'+empty :: NameSet k+empty = NameSet $ IntSet.empty++-- | The singleton 'NameSet'+singleton :: Name (a::k) -> NameSet k+singleton (MkName i) = NameSet $ IntSet.singleton $ i++-- | Convert a list of names to a 'NameSet'+fromList :: [SomeName k] -> NameSet k+fromList =+  NameSet . IntSet.fromList . Prelude.map (\(SomeName (MkName i)) -> i)++-- | Convert a 'NameSet' to a list+toList :: NameSet k -> [SomeName k]+toList (NameSet s) = Prelude.map (SomeName . MkName) (IntSet.toList s)++-- | Insert a name into a 'NameSet'+insert :: Name (a::k) -> NameSet k -> NameSet k+insert (MkName i) (NameSet s) = NameSet $ IntSet.insert i s++-- | Delete a name from a 'NameSet'+delete :: Name (a::k) -> NameSet k -> NameSet k+delete (MkName i) (NameSet s) = NameSet $ IntSet.delete i s++-- | Test if a name is in a 'NameSet'+member :: Name (a::k) -> NameSet k -> Bool+member (MkName i) (NameSet s) = IntSet.member i s++-- | Test if a 'NameSet' is empty+null :: NameSet k -> Bool+null (NameSet s) = IntSet.null s++-- | Compute the cardinality of a 'NameSet'+size :: NameSet k -> Int+size (NameSet s) = IntSet.size s++-- | Take the union of two 'NameSet's+union :: NameSet k -> NameSet k -> NameSet k+union (NameSet s1) (NameSet s2) = NameSet $ IntSet.union s1 s2++-- | Take the union of a list of 'NameSet's+unions :: Foldable f => f (NameSet k) -> NameSet k+unions = Foldable.foldl' union empty++-- | Take the set of all elements of the first 'NameSet' not in the second+difference :: NameSet k -> NameSet k -> NameSet k+difference (NameSet s1) (NameSet s2) = NameSet $ IntSet.difference s1 s2++-- | Another name for 'difference'+(\\) :: NameSet k -> NameSet k -> NameSet k+(\\) = difference++-- | Take the intersection of two 'NameSet's+intersection :: NameSet k -> NameSet k -> NameSet k+intersection (NameSet s1) (NameSet s2) = NameSet $ IntSet.intersection s1 s2++-- | Map a function across all elements of a 'NameSet'+map :: (forall (a::k). Name a -> Name a) -> NameSet k -> NameSet k+map f (NameSet s) =+  NameSet $ IntSet.map (\i -> let (MkName j) = f (MkName i) in j) s++-- | Perform a right fold of a function across all elements of a 'NameSet'+foldr :: (forall (a::k). Name a -> r -> r) -> r -> NameSet k -> r+foldr f r (NameSet s) = IntSet.foldr (f . MkName) r s++-- | Perform a left fold of a function across all elements of a 'NameSet'+foldl :: (forall (a::k). r -> Name a -> r) -> r -> NameSet k -> r+foldl f r (NameSet s) = IntSet.foldl (\r -> f r . MkName) r s++-- | Lift a 'NameSet' out of a name-binding by lifting all names not bound by+-- the name-binding and then forming a 'NameSet' from those lifted names+liftNameSet :: Mb ctx (NameSet (k :: Type)) -> NameSet k+liftNameSet mb_s = fromList $ mapMaybe helper $ mbList $ fmap toList mb_s+  where+    helper :: forall ctx' k'. Mb ctx' (SomeName k') -> Maybe (SomeName k')+    helper [nuP| SomeName mb_n |]+      | Right n <- mbNameBoundP mb_n = Just (SomeName n)+    helper _ = Nothing
+ src/Data/Binding/Hobbits/NuMatching.hs view
@@ -0,0 +1,579 @@+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE PolyKinds #-}+{-# LANGUAGE QuasiQuotes #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE UndecidableInstances #-}+{-# LANGUAGE ViewPatterns #-}++-- |+-- Module      : Data.Binding.Hobbits.NuMatching+-- Copyright   : (c) 2014 Edwin Westbrook, Nicolas Frisby, and Paul Brauner+--+-- License     : BSD3+--+-- Maintainer  : westbrook@kestrel.edu+-- Stability   : experimental+-- Portability : GHC+--+-- This module defines the typeclass @'NuMatching' a@, which allows+-- pattern-matching on the bodies of multi-bindings when their bodies+-- have type a. To ensure adequacy, the actual machinery of how this+-- works is hidden from the user, but, for any given (G)ADT @a@, the+-- user can use the Template Haskell function 'mkNuMatching' to+-- create a 'NuMatching' instance for @a@.+--+++module Data.Binding.Hobbits.NuMatching (+  NuMatching(..), mkNuMatching,+  MbTypeRepr(), isoMbTypeRepr, unsafeMbTypeRepr,+  NuMatchingAny1(..)+) where++import Data.Vector (Vector)+import qualified Data.Vector as Vector+--import Data.Typeable+import Language.Haskell.TH hiding (Name, Type(..))+import qualified Language.Haskell.TH as TH+import Control.Monad.State+import Numeric.Natural+import Data.Functor.Constant+import Data.Kind as DK+import Data.Word+import Data.Proxy+import Data.Type.Equality+--import Control.Monad.Identity++import Data.Type.RList hiding (map)+import Data.Binding.Hobbits.Internal.Name+import Data.Binding.Hobbits.Internal.Mb+import Data.Binding.Hobbits.Internal.Closed+++{-| Just like 'mapNamesPf', except uses the NuMatching class. -}+mapNames :: NuMatching a => NameRefresher -> a -> a+mapNames = mapNamesPf nuMatchingProof++matchDataDecl :: Dec -> Maybe (Cxt, TH.Name, [TyVarBndr], [Con])+matchDataDecl (DataD cxt name tyvars _ constrs _) =+  Just (cxt, name, tyvars, constrs)+matchDataDecl (NewtypeD cxt name tyvars _ constr _) =+  Just (cxt, name, tyvars, [constr])+matchDataDecl _ = Nothing+++mkInstanceD :: Cxt -> TH.Type -> [Dec] -> Dec+mkInstanceD = InstanceD Nothing++{-|+  Instances of the @'NuMatching' a@ class allow pattern-matching on+  multi-bindings whose bodies have type @a@, i.e., on multi-bindings+  of type @'Mb' ctx a@. The structure of this class is mostly hidden+  from the user; see 'mkNuMatching' to see how to create instances+  of the @NuMatching@ class.+-}+class NuMatching a where+    nuMatchingProof :: MbTypeRepr a++-- | Build an 'MbTypeRepr' for type @a@ by using an isomorphism with an+-- already-representable type @b@. This is useful for building 'NuMatching'+-- instances for, e.g., 'Integral' types, by mapping to and from 'Integer',+-- without having to define instances for each one in this module.+isoMbTypeRepr :: NuMatching b => (a -> b) -> (b -> a) -> MbTypeRepr a+isoMbTypeRepr f_to f_from =+  MbTypeReprData $ MkMbTypeReprData $ \refresher a ->+  f_from $ mapNames refresher (f_to a)++-- | Builds an 'MbTypeRepr' proof for use in a 'NuMatching' instance. This proof+-- is unsafe because it does no renaming of fresh names, so should only be used+-- for types that are guaranteed not to contain any 'Name' or 'Mb' values.+unsafeMbTypeRepr :: MbTypeRepr a+unsafeMbTypeRepr = MbTypeReprData (MkMbTypeReprData $ (\_ -> id))++instance NuMatching (Name a) where+    nuMatchingProof = MbTypeReprName++instance NuMatching (Closed a) where+    -- no need to map free variables in a Closed object+    nuMatchingProof = MbTypeReprData (MkMbTypeReprData $ (\refresher -> id))++instance (NuMatching a, NuMatching b) => NuMatching (a -> b) where+    nuMatchingProof = MbTypeReprFun nuMatchingProof nuMatchingProof++instance NuMatching a => NuMatching (Mb ctx a) where+    nuMatchingProof = MbTypeReprMb nuMatchingProof++instance NuMatching Bool where+    nuMatchingProof = MbTypeReprData (MkMbTypeReprData $ (\_ -> id))++instance NuMatching Int where+    nuMatchingProof = MbTypeReprData (MkMbTypeReprData $ (\_ -> id))++instance NuMatching Integer where+    nuMatchingProof = MbTypeReprData (MkMbTypeReprData $ (\_ -> id))++instance NuMatching Char where+    nuMatchingProof = MbTypeReprData (MkMbTypeReprData $ (\_ -> id))++instance NuMatching Natural where+    nuMatchingProof = MbTypeReprData (MkMbTypeReprData $ (\_ -> id))++instance NuMatching Float where+    nuMatchingProof = MbTypeReprData (MkMbTypeReprData $ (\_ -> id))++instance NuMatching Double where+    nuMatchingProof = MbTypeReprData (MkMbTypeReprData $ (\_ -> id))++instance NuMatching Word where+    nuMatchingProof = MbTypeReprData (MkMbTypeReprData $ (\_ -> id))++instance NuMatching Word8 where+    nuMatchingProof = MbTypeReprData (MkMbTypeReprData $ (\_ -> id))++instance NuMatching Word16 where+    nuMatchingProof = MbTypeReprData (MkMbTypeReprData $ (\_ -> id))++instance NuMatching Word32 where+    nuMatchingProof = MbTypeReprData (MkMbTypeReprData $ (\_ -> id))++instance NuMatching Word64 where+    nuMatchingProof = MbTypeReprData (MkMbTypeReprData $ (\_ -> id))++instance NuMatching () where+    nuMatchingProof = MbTypeReprData (MkMbTypeReprData $ (\_ -> id))++instance (NuMatching a, NuMatching b) => NuMatching (a,b) where+    nuMatchingProof = MbTypeReprData (MkMbTypeReprData $ \r (a,b) ->+                                       (mapNames r a, mapNames r b))++instance (NuMatching a, NuMatching b, NuMatching c) => NuMatching (a,b,c) where+    nuMatchingProof = MbTypeReprData (MkMbTypeReprData $ \r (a,b,c) ->+                                       (mapNames r a, mapNames r b, mapNames r c))++instance (NuMatching a, NuMatching b,+          NuMatching c, NuMatching d) => NuMatching (a,b,c,d) where+    nuMatchingProof = MbTypeReprData (MkMbTypeReprData $ \r (a,b,c,d) ->+                                       (mapNames r a, mapNames r b,+                                        mapNames r c, mapNames r d))++instance NuMatching a => NuMatching [a] where+    nuMatchingProof = MbTypeReprData (MkMbTypeReprData $ (\r -> map (mapNames r)))++instance NuMatching a => NuMatching (Vector a) where+    nuMatchingProof =+      MbTypeReprData (MkMbTypeReprData $ (\r -> Vector.map (mapNames r)))+++{-+type family NuMatchingListProof args+type instance NuMatchingListProof Nil = ()+type instance NuMatchingListProof (args :> arg) = (NuMatchingListProof args, MbTypeReprData arg)++-- the NuMatchingList class, for saying that NuMatching holds for a context of types+class NuMatchingList args where+    nuMatchingListProof :: NuMatchingListProof args++instance NuMatchingList Nil where+    nuMatchingListProof = ()++instance (NuMatchingList args, NuMatching a) => NuMatchingList (args :> a) where+    nuMatchingListProof = (nuMatchingListProof, nuMatchingProof)+-}++{-+-- | An object-level reification of the 'NuMatching' class+data NuMatchingObj a = NuMatching a => NuMatchingObj ()++class NuMatchingList args where+    nuMatchingListProof :: RAssign NuMatchingObj args++instance NuMatchingList RNil where+    nuMatchingListProof = MNil++instance (NuMatchingList args, NuMatching a) => NuMatchingList (args :> a) where+    nuMatchingListProof = nuMatchingListProof :>: NuMatchingObj ()+++class NuMatching1 f where+    nuMatchingProof1 :: NuMatching a => NuMatchingObj (f a)+-}++-- README: deriving NuMatching from NuMatching1 leads to overlapping instances+-- for, e.g., Name a+{-+instance (NuMatching1 f, NuMatching a) => NuMatching (f a) where+    nuMatchingProof = nuMatchingProof1 nuMatchingProof+-}++{-+instance {-# OVERLAPPABLE #-} (NuMatching1 f, NuMatchingList ctx) =>+                              NuMatching (RAssign f ctx) where+    nuMatchingProof = MbTypeReprData $ MkMbTypeReprData $ helper nuMatchingListProof where+        helper :: NuMatching1 f =>+                  RAssign NuMatchingObj args -> NameRefresher ->+                  RAssign f args -> RAssign f args+        helper MNil r MNil = MNil+        helper (proofs :>: NuMatchingObj ()) r (elems :>: (elem :: f a)) =+            case nuMatchingProof1 :: NuMatchingObj (f a) of+              NuMatchingObj () ->+                  (helper proofs r elems) :>:+                  mapNames r elem+-}++-- | Typeclass for lifting the 'NuMatching' constraint to functors on arbitrary+-- kinds that do not require any constraints on their input types+class NuMatchingAny1 (f :: k -> Type) where+  nuMatchingAny1Proof :: MbTypeRepr (f a)++instance {-# INCOHERENT #-} NuMatchingAny1 f => NuMatching (f a) where+  nuMatchingProof = nuMatchingAny1Proof++instance NuMatchingAny1 Name where+  nuMatchingAny1Proof = nuMatchingProof++instance NuMatchingAny1 ((:~:) a) where+  nuMatchingAny1Proof = nuMatchingProof++instance NuMatching a => NuMatchingAny1 (Constant a) where+  nuMatchingAny1Proof = nuMatchingProof++instance {-# OVERLAPPABLE #-} NuMatchingAny1 f => NuMatching (RAssign f ctx) where+    nuMatchingProof = MbTypeReprData $ MkMbTypeReprData helper where+        helper :: NuMatchingAny1 f => NameRefresher -> RAssign f args ->+                  RAssign f args+        helper r MNil = MNil+        helper r (elems :>: elem) = helper r elems :>: mapNames r elem+++-- now we define some TH to create NuMatchings++natsFrom i = i : natsFrom (i+1)++fst3 :: (a,b,c) -> a+fst3 (x,_,_) = x++snd3 :: (a,b,c) -> b+snd3 (_,y,_) = y++thd3 :: (a,b,c) -> c+thd3 (_,_,z) = z+++type Names = (TH.Name, TH.Name, TH.Name)++mapNamesType a = [t| forall ctx. NameRefresher -> $a -> $a |]++{-|+  Template Haskell function for creating NuMatching instances for (G)ADTs.+  Typical usage is to include the following line in the source file for+  (G)ADT @T@ (here assumed to have two type arguments):++> $(mkNuMatching [t| forall a b . T a b |])++  The 'mkNuMatching' call here will create an instance declaration for+  @'NuMatching' (T a b)@. It is also possible to include a context in the+  forall type; for example, if we define the 'ID' data type as follows:++> data ID a = ID a++  then we can create a 'NuMatching' instance for it like this:++> $( mkNuMatching [t| NuMatching a => ID a |])++  Note that, when a context is included, the Haskell parser will add+  the @forall a@ for you.+-}+mkNuMatching :: Q TH.Type -> Q [Dec]+mkNuMatching tQ =+    do t <- tQ+       (cxt, cType, tName, constrs, tyvars) <- getMbTypeReprInfoTop t+       fName <- newName "f"+       refrName <- newName "refresher"+       clauses <- getClauses (tName, fName, refrName) constrs+       mapNamesT <- mapNamesType (return cType)+       return [mkInstanceD+               cxt (TH.AppT (TH.ConT ''NuMatching) cType)+               [ValD (VarP 'nuMatchingProof)+                (NormalB+                 $ AppE (ConE 'MbTypeReprData)+                   $ AppE (ConE 'MkMbTypeReprData)+                         $ LetE [SigD fName+                                 $ TH.ForallT (map PlainTV tyvars) cxt mapNamesT,+                                 FunD fName clauses]+                               (VarE fName)) []]]++       {-+       return (LetE+               [SigD fName+                     (TH.ForallT tyvars reqCxt+                     $ foldl TH.AppT TH.ArrowT+                           [foldl TH.AppT (TH.ConT conName)+                                      (map tyVarToType tyvars)]),+                FunD fname clauses]+               (VarE fname))+        -}+    where+      -- extract the name from a TyVarBndr+      tyBndrToName (PlainTV n) = n+      tyBndrToName (KindedTV n _) = n++      -- fail for getMbTypeReprInfo+      getMbTypeReprInfoFail t extraMsg =+          fail ("mkMbTypeRepr: " ++ show t+                ++ " is not a type constructor for a (G)ADT applied to zero or more distinct type variables" ++ extraMsg)++      -- get info for conName (top-level call)+      getMbTypeReprInfoTop t = getMbTypeReprInfo [] [] t t++      -- get info for conName+      getMbTypeReprInfo ctx tyvars topT (TH.ConT tName) =+          do info <- reify tName+             case info of+               TyConI (matchDataDecl -> Just (_, _, tyvarsReq, constrs)) ->+                 success tyvarsReq constrs+               _ -> getMbTypeReprInfoFail topT (": info for " ++ (show tName) ++ " = " ++ (show info))+          where+            success tyvarsReq constrs =+                let tyvarsRet = if tyvars == [] && ctx == []+                                then map tyBndrToName tyvarsReq+                                else tyvars in+                return (ctx,+                        foldl TH.AppT (TH.ConT tName) (map TH.VarT tyvars),+                        tName, constrs, tyvarsRet)++      getMbTypeReprInfo ctx tyvars topT (TH.AppT f (TH.VarT argName)) =+          if elem argName tyvars then+              getMbTypeReprInfoFail topT ""+          else+              getMbTypeReprInfo ctx (argName:tyvars) topT f++      getMbTypeReprInfo ctx tyvars topT (TH.ForallT _ ctx' t) =+          getMbTypeReprInfo (ctx ++ ctx') tyvars topT t++      getMbTypeReprInfo ctx tyvars topT t = getMbTypeReprInfoFail topT ""++      -- get the name from a data type+      getTCtor t = getTCtorHelper t t []+      getTCtorHelper (TH.ConT tName) topT tyvars = Just (topT, tName, tyvars)+      getTCtorHelper (TH.AppT t1 (TH.VarT var)) topT tyvars =+          getTCtorHelper t1 topT (tyvars ++ [var])+      getTCtorHelper (TH.SigT t1 _) topT tyvars = getTCtorHelper t1 topT tyvars+      getTCtorHelper _ _ _ = Nothing++      -- get a list of Clauses, one for each constructor in constrs+      getClauses :: Names -> [Con] -> Q [Clause]+      getClauses _ [] = return []++      getClauses names (NormalC cName cTypes : constrs) =+        do clause <-+             getClauseHelper names (map snd cTypes) (natsFrom 0)+             (\l -> ConP cName (map (VarP . fst3) l))+             (\l -> foldl AppE (ConE cName) (map fst3 l))+           clauses <- getClauses names constrs+           return $ clause : clauses++      getClauses names (RecC cName cVarTypes : constrs) =+        do clause <-+             getClauseHelper names (map thd3 cVarTypes) (map fst3 cVarTypes)+             (\l -> RecP cName (map (\(var,_,field) -> (field, VarP var)) l))+             (\l -> RecConE cName (map (\(exp,_,field) -> (field, exp)) l))+           clauses <- getClauses names constrs+           return $ clause : clauses++      getClauses names (InfixC cType1 cName cType2 : constrs) =+        do clause <-+             getClauseHelper names (map snd [cType1, cType2]) (natsFrom 0)+             (\l -> ConP cName (map (VarP . fst3) l))+             (\l -> foldl AppE (ConE cName) (map fst3 l))+           clauses <- getClauses names constrs+           return $ clause : clauses++      getClauses names (GadtC cNames cTypes _ : constrs) =+        do clauses1 <-+             forM cNames $ \cName ->+             getClauseHelper names (map snd cTypes) (natsFrom 0)+             (\l -> ConP cName (map (VarP . fst3) l))+             (\l -> foldl AppE (ConE cName) (map fst3 l))+           clauses2 <- getClauses names constrs+           return (clauses1 ++ clauses2)++      getClauses names (RecGadtC cNames cVarTypes _ : constrs) =+        do clauses1 <-+             forM cNames $ \cName ->+             getClauseHelper names (map thd3 cVarTypes) (map fst3 cVarTypes)+             (\l -> RecP cName (map (\(var,_,field) -> (field, VarP var)) l))+             (\l -> RecConE cName (map (\(exp,_,field) -> (field, exp)) l))+           clauses2 <- getClauses names constrs+           return (clauses1 ++ clauses2)++      getClauses names (ForallC _ _ constr : constrs) =+        getClauses names (constr : constrs)++      getClauseHelper :: Names -> [TH.Type] -> [a] ->+                         ([(TH.Name,TH.Type,a)] -> Pat) ->+                         ([(Exp,TH.Type,a)] -> Exp) ->+                         Q Clause+      getClauseHelper names@(tName, fName, refrName) cTypes cData pFun eFun =+          do varNames <- mapM (newName . ("x" ++) . show . fst)+                         $ zip (natsFrom 0) cTypes+             let varsTypesData = zip3 varNames cTypes cData+             let expsTypesData = map (mkExpTypeData names) varsTypesData+             return $ Clause [(VarP refrName), (pFun varsTypesData)]+                        (NormalB $ eFun expsTypesData) []++      mkExpTypeData :: Names -> (TH.Name,TH.Type,a) -> (Exp,TH.Type,a)+      mkExpTypeData (tName, fName, refrName)+                    (varName, getTCtor -> Just (t, tName', _), cData)+          | tName == tName' =+              -- the type of the arg is the same as the (G)ADT we are+              -- recursing over; apply the recursive function+              (foldl AppE (VarE fName)+                         [(VarE refrName), (VarE varName)],+               t, cData)+      mkExpTypeData (tName, fName, refrName) (varName, t, cData) =+          -- the type of the arg is not the same as the (G)ADT; call mapNames+          (foldl AppE (VarE 'mapNames)+                     [(VarE refrName), (VarE varName)],+           t, cData)++-- FIXME: old stuff below++type CxtStateQ a = StateT Cxt Q a++-- create a MkMbTypeReprData for a (G)ADT+mkMkMbTypeReprDataOld :: Q TH.Name -> Q Exp+mkMkMbTypeReprDataOld conNameQ =+    do conName <- conNameQ+       (cxt, name, tyvars, constrs) <- getMbTypeReprInfo conName+       (clauses, reqCxt) <- runStateT (getClauses cxt name tyvars [] constrs) []+       fname <- newName "f"+       return (LetE+               [SigD fname+                     (TH.ForallT tyvars reqCxt+                     $ foldl TH.AppT TH.ArrowT+                           [foldl TH.AppT (TH.ConT conName)+                                      (map tyVarToType tyvars)]),+                FunD fname clauses]+               (VarE fname))+    where+      -- convert a TyVar to a Name+      tyVarToType (PlainTV n) = TH.VarT n+      tyVarToType (KindedTV n _) = TH.VarT n++      -- get info for conName+      getMbTypeReprInfo conName =+          reify conName >>= \info ->+              case info of+                TyConI (matchDataDecl -> Just (cxt, name, tyvars, constrs)) ->+                    return (cxt, name, tyvars, constrs)+                _ -> fail ("mkMkMbTypeReprData: " ++ show conName+                           ++ " is not a (G)ADT")+      {-+      -- report failure+      getMbTypeReprInfoFail t =+          fail ("mkMkMbTypeReprData: " ++ show t+                ++ " is not a fully applied (G)ADT")++      getMbTypeReprInfo (TH.ConT conName) topT =+          reify conName >>= \info ->+              case info of+                TyConI (DataD cxt name tyvars constrs _) ->+                    return (cxt, name, tyvars, constrs)+                _ -> getMbTypeReprInfoFail topT+      getMbTypeReprInfo (TH.AppT t _) topT = getMbTypeReprInfo t topT+      getMbTypeReprInfo (TH.SigT t _) topT = getMbTypeReprInfo t topT+      getMbTypeReprInfo _ topT = getMbTypeReprInfoFail topT+       -}++      -- get a list of Clauses, one for each constructor in constrs+      getClauses :: Cxt -> TH.Name -> [TyVarBndr] -> [TyVarBndr] -> [Con] ->+                    CxtStateQ [Clause]+      getClauses cxt name tyvars locTyvars [] = return []++      getClauses cxt name tyvars locTyvars (NormalC cName cTypes : constrs) =+        do clause <-+             getClauseHelper cxt name tyvars locTyvars (map snd cTypes)+             (natsFrom 0)+             (\l -> ConP cName (map (VarP . fst3) l))+             (\l -> foldl AppE (ConE cName) (map (VarE . fst3) l))+           clauses <- getClauses cxt name tyvars locTyvars constrs+           return (clause : clauses)++      getClauses cxt name tyvars locTyvars (RecC cName cVarTypes : constrs) =+        do clause <-+             getClauseHelper cxt name tyvars locTyvars (map thd3 cVarTypes)+             (map fst3 cVarTypes)+             (\l -> RecP cName (map (\(var,_,field) -> (field, VarP var)) l))+             (\l -> RecConE cName (map (\(var,_,field) -> (field, VarE var)) l))+           clauses <- getClauses cxt name tyvars locTyvars constrs+           return (clause : clauses)++      getClauses cxt name tyvars locTyvars (InfixC cType1 cName cType2 : _) =+        undefined -- FIXME++      getClauses cxt name tyvars locTyvars (ForallC tyvars2 cxt2 constr+                                            : constrs) =+        do clauses1 <-+             getClauses (cxt ++ cxt2) name tyvars (locTyvars ++ tyvars2) [constr]+           clauses2 <- getClauses cxt name tyvars locTyvars constrs+           return (clauses1 ++ clauses2)++      getClauses cxt name tyvars locTyvars (GadtC cNames cTypes _ : constrs) =+        do clauses1 <-+             forM cNames $ \cName ->+             getClauseHelper cxt name tyvars locTyvars (map snd cTypes)+             (natsFrom 0) (\l -> ConP cName (map (VarP . fst3) l))+             (\l -> foldl AppE (ConE cName) (map (VarE . fst3) l))+           clauses2 <- getClauses cxt name tyvars locTyvars constrs+           return (clauses1 ++ clauses2)++      getClauses cxt name tyvars locTyvars (RecGadtC cNames cVarTypes _+                                            : constrs) =+        do clauses1 <-+             forM cNames $ \cName ->+             getClauseHelper cxt name tyvars locTyvars+             (map thd3 cVarTypes) (map fst3 cVarTypes)+             (\l -> RecP cName (map (\(var,_,field) -> (field, VarP var)) l))+             (\l -> RecConE cName (map (\(var,_,field) -> (field, VarE var)) l))+           clauses2 <- getClauses cxt name tyvars locTyvars constrs+           return (clauses1 ++ clauses2)++      getClauseHelper :: Cxt -> TH.Name -> [TyVarBndr] -> [TyVarBndr] ->+                         [TH.Type] -> [a] ->+                         ([(TH.Name,TH.Type,a)] -> Pat) ->+                         ([(TH.Name,TH.Type,a)] -> Exp) ->+                         CxtStateQ Clause+      getClauseHelper cxt name tyvars locTyvars cTypes cData pFun eFun =+          do varNames <- mapM (lift . newName . ("x" ++) . show . fst)+                         $ zip (natsFrom 0) cTypes+             () <- ensureCxt cxt locTyvars cTypes+             let varsTypesData = zip3 varNames cTypes cData+             return $ Clause [(pFun varsTypesData)]+                        (NormalB $ eFun varsTypesData) []++      -- ensure that MbTypeRepr a holds for each type a in cTypes+      ensureCxt :: Cxt -> [TyVarBndr] -> [TH.Type] -> CxtStateQ ()+      ensureCxt cxt locTyvars cTypes =+          foldM (const (ensureCxt1 cxt locTyvars)) () cTypes++      -- FIXME: it is not possible (or, at least, not easy) to determine+      -- if MbTypeRepr a is implied from a current Cxt... so we just add+      -- everything we need to the returned Cxt, except for +      ensureCxt1 :: Cxt -> [TyVarBndr] -> TH.Type -> CxtStateQ ()+      ensureCxt1 cxt locTyvars t = undefined+      {-+      ensureCxt1 cxt locTyvars t = do+        curCxt = get+        let fullCxt = cxt ++ curCxt+        isOk <- isMbTypeRepr fullCxt ++      isMbTypeRepr +       -}
+ src/Data/Binding/Hobbits/NuMatchingInstances.hs view
@@ -0,0 +1,40 @@+{-# LANGUAGE GADTs #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE PolyKinds #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE ViewPatterns #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE QuasiQuotes #-}++-- |+-- Module      : Data.Binding.Hobbits.NuMatchingInstances+-- Copyright   : (c) 2020 Edwin Westbrook+--+-- License     : BSD3+--+-- Maintainer  : westbrook@galois.com+-- Stability   : experimental+-- Portability : GHC+--+-- Provides a set of instances of 'NuMatching' for standard types using the+-- template Haskell 'mkNuMatching' function++module Data.Binding.Hobbits.NuMatchingInstances where++import Data.Proxy+import Data.Type.Equality+import Data.Functor.Constant++import Data.Type.RList+import Data.Binding.Hobbits.Mb+import Data.Binding.Hobbits.NuMatching (NuMatching, NuMatchingAny1, mkNuMatching)+import Data.Binding.Hobbits.QQ (nuP)++$(mkNuMatching [t| forall a. NuMatching a => Maybe a |])+$(mkNuMatching [t| forall a b. (NuMatching a, NuMatching b) => Either a b |])+$(mkNuMatching [t| forall ctx a. Member ctx a |])+$(mkNuMatching [t| forall a. Proxy a |])+$(mkNuMatching [t| forall a b. a :~: b |])+$(mkNuMatching [t| forall a b. NuMatching a => Constant a b |])
+ src/Data/Binding/Hobbits/PatternParser.hs view
@@ -0,0 +1,34 @@+-- |+-- Module      : Data.Binding.Hobbits.PatternParser+-- Copyright   : (c) 2011 Edwin Westbrook, Nicolas Frisby, and Paul Brauner+--+-- License     : BSD3+--+-- Maintainer  : emw4@rice.edu+-- Stability   : experimental+-- Portability : GHC+--+-- Using the haskell-src-meta package to parse Haskell patterns.++module Data.Binding.Hobbits.PatternParser (parsePattern) where++import Language.Haskell.TH++import qualified Language.Haskell.Exts.Parser as Meta++import qualified Language.Haskell.Meta.Parse as Meta++import qualified Language.Haskell.Meta.Parse as Sloppy+import qualified Language.Haskell.Meta.Syntax.Translate as Translate++import qualified Language.Haskell.Exts.Extension as Exts++parsePatternExtensions =+  map Exts.EnableExtension $ Exts.ViewPatterns : Sloppy.myDefaultExtensions++parsePattern :: String -> String -> Either String Pat+parsePattern fn =+  fmap Translate.toPat . Meta.parseResultToEither .+  Meta.parsePatWithMode (Sloppy.myDefaultParseMode+                    {Meta.parseFilename = fn,+                     Meta.extensions = parsePatternExtensions })
+ src/Data/Binding/Hobbits/QQ.hs view
@@ -0,0 +1,148 @@+{-# LANGUAGE TemplateHaskell, FlexibleContexts, PolyKinds #-}++-- |+-- Module      : Data.Binding.Hobbits.QQ+-- Copyright   : (c) 2011 Edwin Westbrook, Nicolas Frisby, and Paul Brauner+--+-- License     : BSD3+--+-- Maintainer  : emw4@rice.edu+-- Stability   : experimental+-- Portability : GHC+--+-- Defines a quasi-quoter for writing patterns that match the bodies of 'Mb'+-- multi-bindings. Uses the haskell-src-exts parser. @[nuP| P ]@ defines a+-- pattern that will match a multi-binding whose body matches @P@. Any+-- variables matched by @P@ will remain inside the binding; thus, for example,+-- in the pattern @[nuP| x |]@, @x@ matches the entire multi-binding.+--+-- Examples:+--+-- > case (nu Left) of [nuP| Left x |] -> x  ==  nu id+--+-- @[clP| P |]@ does the same for the 'Closed' type, and @[clNuP| P |]@ works+-- for both simultaneously: @'Closed' ('Mb' ctx a)@.++module Data.Binding.Hobbits.QQ (nuP, clP, clNuP) where++import Language.Haskell.TH.Syntax as TH+import Language.Haskell.TH.Ppr as TH+import Language.Haskell.TH.Quote++import qualified Data.Generics as SYB+import Control.Monad.Writer (runWriterT, tell)+import Data.Monoid (Any(..))++import qualified Data.Binding.Hobbits.Internal.Utilities as IU+import Data.Binding.Hobbits.Internal.Mb+import Data.Binding.Hobbits.Internal.Closed+import Data.Binding.Hobbits.PatternParser (parsePattern)+import Data.Binding.Hobbits.NuMatching+++-- | Helper function to apply an expression to multiple arguments+appEMulti :: Exp -> [Exp] -> Exp+appEMulti = foldl AppE++-- | Helper function to apply the (.) operator on expressions+compose :: Exp -> Exp -> Exp+compose f g = VarE '(.) `AppE` f `AppE` g++-- | @patQQ str pat@ builds a quasi-quoter named @str@ that parses+-- | patterns with @pat@+patQQ :: String -> (String -> Q Pat) -> QuasiQuoter+patQQ n pat = QuasiQuoter (err "Exp") pat (err "Type") (err "Decs")+  where err s = error $ "QQ `" ++ n ++ "' is for patterns, not " ++ s ++ "."+++-- | A @WrapKit@ specifies a transformation to be applied to variables+-- | in a Template Haskell patterns, as follows:+--+-- * @_varView@ gives an expression for a function to be applied, as a+--   view pattern, to variables before matching them, including to+--   variables bound by @\@@ patterns;+--+-- * @_asXform@ gives a function to transform the bodies of \@+--   patterns, i.e., this function is applied to @p@ in pattern @x\@p@;+--+-- * @_topXform@ gives a function to transform the whole pattern after+--    @_varView@ and/or @_asXform@ have been applied to sub-patterns;+--    as the first argument, @_topXform@ also takes a flag indicating+--    whether any transformations have been applied to sub-patterns.+--+data WrapKit =+  WrapKit {_varView :: Exp, _asXform :: Pat -> Pat, _topXform :: Bool -> Pat -> Pat}++-- | Combine two WrapKits, composing the individual components+combineWrapKits :: WrapKit -> WrapKit -> WrapKit+combineWrapKits (WrapKit {_varView = varViewO, _asXform = asXformO, _topXform = topXformO})+           (WrapKit {_varView = varViewI, _asXform = asXformI, _topXform = topXformI}) =+  WrapKit {_varView = varViewO `compose` varViewI,+           _asXform = asXformO . asXformI,+           _topXform = \b -> topXformO b . topXformI b}++-- | Apply a 'WrapKit' to a pattern+wrapVars :: Monad m => WrapKit -> Pat -> m Pat+wrapVars (WrapKit {_varView = varView, _asXform = asXform, _topXform = topXform}) pat = do+  (pat', Any usedVarView) <- runWriterT m+  return $ topXform usedVarView pat'+  where+    m = IU.everywhereButM (SYB.mkQ False isExp) (SYB.mkM w) pat+      where isExp :: Exp -> Bool+            -- don't recur into the expression part of view patterns+            isExp _ = True++    -- this should be called if the 'varView' function is ever used+    hit x = tell (Any True) >> return x++    -- wraps up bound names+    w p@VarP{} = hit $ ViewP varView p+    -- wraps for the bound name, then immediately unwraps+    -- for the rest of the pattern+    w (AsP v p) = hit $ ViewP varView $ AsP v $ asXform p+    -- requires the expression to be closed+    w (ViewP (VarE n) p) = return $ ViewP (VarE 'unClosed `AppE` VarE n) p+    w (ViewP e _) = fail $ "view function must be a single name: `" ++ show (TH.ppr e) ++ "'"+    w p = return p++-- | Parse a pattern from a string, using 'parsePattern'+parseHere :: String -> Q Pat+parseHere s = do+  fn <- loc_filename `fmap` location+  case parsePattern fn s of+    Left e -> error $ "Parse error: `" ++ e +++      "'\n\n\t when parsing pattern: `" ++ s ++ "'."+    Right p -> return p+++-- | A helper function used to ensure two multi-bindings have the same contexts+same_ctx :: Mb ctx a -> Mb ctx b -> Mb ctx b+same_ctx _ x = x++-- | Builds a 'WrapKit' for parsing patterns that match over 'Mb'.+-- | Takes two fresh names as arguments.+nuKit :: TH.Name -> TH.Name -> WrapKit+nuKit topVar namesVar = WrapKit {_varView = varView, _asXform = asXform, _topXform = topXform} where+  varView = (VarE 'same_ctx `AppE` VarE topVar) `compose`+        (appEMulti (ConE 'MkMbPair) [VarE 'nuMatchingProof, VarE namesVar])+  asXform p = ViewP (VarE 'ensureFreshPair) (TupP [WildP, p])+  topXform b p = if b then AsP topVar $ ViewP (VarE 'ensureFreshPair) (TupP [VarP namesVar, p]) else asXform p++-- | Quasi-quoter for patterns that match over 'Mb'+nuP = patQQ "nuP" $ \s -> do+  topVar <- newName "topMb"+  namesVar <- newName "topNames"+  parseHere s >>= wrapVars (nuKit topVar namesVar)++-- | Builds a 'WrapKit' for parsing patterns that match over 'Closed'+clKit = WrapKit {_varView = ConE 'Closed, _asXform = asXform, _topXform = const asXform}+  where asXform p = ConP 'Closed [p]++-- | Quasi-quoter for patterns that match over 'Closed', built using 'clKit'+clP = patQQ "clP" $ (>>= wrapVars clKit) . parseHere++-- | Quasi-quoter for patterns that match over @'Closed' ('Mb' ctx a)@+clNuP = patQQ "clNuP" $ \s -> do+  topVar <- newName "topMb"+  namesVar <- newName "topNames"+  parseHere s >>= wrapVars (clKit `combineWrapKits` nuKit topVar namesVar)
+ src/Data/Type/RList.hs view
@@ -0,0 +1,232 @@+{-# LANGUAGE TypeOperators, EmptyDataDecls, RankNTypes #-}+{-# LANGUAGE TypeFamilies, DataKinds, PolyKinds, KindSignatures #-}+{-# LANGUAGE GADTs, TypeInType, PatternGuards #-}++-- |+-- Module      : Data.Type.RList+-- Copyright   : (c) 2016 Edwin Westbrook+--+-- License     : BSD3+--+-- Maintainer  : westbrook@galois.com+-- Stability   : experimental+-- Portability : GHC+--+-- A /right list/, or 'RList', is a list where cons adds to the end, or the+-- right-hand side, of a list. This is useful conceptually for contexts of+-- name-bindings, where the most recent name-binding is intuitively at the end+-- of the context.++module Data.Type.RList where++import Prelude hiding (map, foldr)+import Data.Kind+import Data.Type.Equality+import Data.Proxy (Proxy(..))+import Data.Functor.Constant+import Data.Typeable++-------------------------------------------------------------------------------+-- * Right-lists as a datatype+-------------------------------------------------------------------------------++-- | A form of lists where elements are added to the right instead of the left+data RList a+  = RNil+  | (RList a) :> a++-- | Append two 'RList's at the type level+type family ((r1 :: RList k) :++: (r2 :: RList k)) :: RList k+infixr 5 :++:+type instance (r :++: 'RNil) = r+type instance (r1 :++: (r2 ':> a)) = (r1 :++: r2) ':> a++-------------------------------------------------------------------------------+-- * Proofs of membership in a type-level list+-------------------------------------------------------------------------------++{-|+  A @Member ctx a@ is a \"proof\" that the type @a@ is in the type+  list @ctx@, meaning that @ctx@ equals++>  t0 ':>' a ':>' t1 ':>' ... ':>' tn++  for some types @t0,t1,...,tn@.+-}+data Member (ctx :: RList k1) (a :: k2) where+  Member_Base :: Member (ctx :> a) a+  Member_Step :: Member ctx a -> Member (ctx :> b) a+  deriving Typeable++instance Show (Member r a) where+  showsPrec p = showsPrecMember (p > 10) where+    showsPrecMember :: Bool -> Member ctx a -> ShowS+    showsPrecMember _ Member_Base = showString "Member_Base"+    showsPrecMember p (Member_Step prf) = showParen p $+      showString "Member_Step" . showsPrec 10 prf++instance TestEquality (Member ctx) where+  testEquality Member_Base Member_Base = Just Refl+  testEquality (Member_Step memb1) (Member_Step memb2)+    | Just Refl <- testEquality memb1 memb2+    = Just Refl+  testEquality _ _ = Nothing++instance Eq (Member ctx a) where+  Member_Base == Member_Base = True+  (Member_Step memb1) == (Member_Step memb2) = memb1 == memb2+  _ == _ = False++--toEq :: Member (Nil :> a) b -> b :~: a+--toEq Member_Base = Refl+--toEq _ = error "Should not happen! (toEq)"++-- | Weaken a 'Member' proof by prepending another context to the context it+-- proves membership in+weakenMemberL :: Proxy r1 -> Member r2 a -> Member (r1 :++: r2) a+weakenMemberL _ Member_Base = Member_Base+weakenMemberL tag (Member_Step mem) = Member_Step (weakenMemberL tag mem)+++------------------------------------------------------------+-- * Proofs that one list equals the append of two others+------------------------------------------------------------++{-|+  An @Append ctx1 ctx2 ctx@ is a \"proof\" that @ctx = ctx1 ':++:' ctx2@.+-}+data Append ctx1 ctx2 ctx where+  Append_Base :: Append ctx RNil ctx+  Append_Step :: Append ctx1 ctx2 ctx -> Append ctx1 (ctx2 :> a) (ctx :> a)++-- | Make an 'Append' proof from any 'RAssign' vector for the second+-- argument of the append.+mkAppend :: RAssign f c2 -> Append c1 c2 (c1 :++: c2)+mkAppend MNil = Append_Base+mkAppend (c :>: _) = Append_Step (mkAppend c)++-- | A version of 'mkAppend' that takes in a 'Proxy' argument.+mkMonoAppend :: Proxy c1 -> RAssign f c2 -> Append c1 c2 (c1 :++: c2)+mkMonoAppend _ = mkAppend++-- | The inverse of 'mkAppend', that builds an 'RAssign' from an 'Append'+proxiesFromAppend :: Append c1 c2 c -> RAssign Proxy c2+proxiesFromAppend Append_Base = MNil+proxiesFromAppend (Append_Step a) = proxiesFromAppend a :>: Proxy+++-------------------------------------------------------------------------------+-- * Contexts+-------------------------------------------------------------------------------++{-|+  An @RAssign f r@ an assignment of an @f a@ for each @a@ in the 'RList' @r@+-}+data RAssign (f :: k -> *) (c :: RList k) where+  MNil :: RAssign f RNil+  (:>:) :: RAssign f c -> f a -> RAssign f (c :> a)++-- | Create an empty 'RAssign' vector.+empty :: RAssign f RNil+empty = MNil++-- | Create a singleton 'RAssign' vector.+singleton :: f a -> RAssign f (RNil :> a)+singleton x = MNil :>: x++-- | Look up an element of an 'RAssign' vector using a 'Member' proof+get :: Member c a -> RAssign f c -> f a+get Member_Base (_ :>: x) = x+get (Member_Step mem') (mc :>: _) = get mem' mc++-- | Heterogeneous type application, including a proof that the input kind of+-- the function equals the kind of the type argument+data HApply (f :: k1 -> Type) (a :: k2) where+  HApply :: forall (f :: k -> Type) (a :: k). f a -> HApply f a++-- | Look up an element of an 'RAssign' vector using a 'Member' proof at what+-- GHC thinks might be a different kind, i.e., heterogeneously+hget :: forall (f :: k1 -> Type) (c :: RList k1) (a :: k2).+        Member c a -> RAssign f c -> HApply f a+hget Member_Base (_ :>: x) = HApply x+hget (Member_Step mem') (mc :>: _) = hget mem' mc++-- | Modify an element of an 'RAssign' vector using a 'Member' proof.+modify :: Member c a -> (f a -> f a) -> RAssign f c -> RAssign f c+modify Member_Base f (xs :>: x) = xs :>: f x+modify (Member_Step mem') f (xs :>: x) = modify mem' f xs :>: x++-- | Set an element of an 'RAssign' vector using a 'Member' proof.+set :: Member c a -> f a -> RAssign f c -> RAssign f c+set memb x = modify memb (const x)++-- | Test if an object is in an 'RAssign', returning a 'Member' proof if it is+memberElem :: TestEquality f => f a -> RAssign f ctx -> Maybe (Member ctx a)+memberElem _ MNil = Nothing+memberElem x (_ :>: y) | Just Refl <- testEquality x y = Just Member_Base+memberElem x (xs :>: _) = fmap Member_Step $ memberElem x xs++-- | Map a function on all elements of an 'RAssign' vector.+map :: (forall x. f x -> g x) -> RAssign f c -> RAssign g c+map _ MNil = MNil+map f (mc :>: x) = map f mc :>: f x++-- | An alternate name for 'map' that does not clash with the prelude+mapRAssign :: (forall x. f x -> g x) -> RAssign f c -> RAssign g c+mapRAssign = map++-- | Map a binary function on all pairs of elements of two 'RAssign' vectors.+map2 :: (forall x. f x -> g x -> h x) ->+                RAssign f c -> RAssign g c -> RAssign h c+map2 _ MNil MNil = MNil+map2 f (xs :>: x) (ys :>: y) = map2 f xs ys :>: f x y++-- | Take the tail of an 'RAssign'+tail :: RAssign f (ctx :> a) -> RAssign f ctx+tail (xs :>: _) = xs++-- | Convert a monomorphic 'RAssign' to a list+toList :: RAssign (Constant a) c -> [a]+toList = mapToList getConstant++-- | Map a function with monomorphic output type across an 'RAssign' to create a+-- standard list:+--+-- > mapToList f = toList . map (Constant . f)+mapToList :: (forall a. f a -> b) -> RAssign f ctx -> [b]+mapToList _ MNil = []+mapToList f (xs :>: x) = mapToList f xs ++ [f x]++-- | Append two 'RAssign' vectors.+append :: RAssign f c1 -> RAssign f c2 -> RAssign f (c1 :++: c2)+append mc MNil = mc+append mc1 (mc2 :>: x) = append mc1 mc2 :>: x++-- | Perform a right fold across an 'RAssign'+foldr :: (forall a. f a -> r -> r) -> r -> RAssign f ctx -> r+foldr _ r MNil = r+foldr f r (xs :>: x) = f x $ foldr f r xs++-- | Split an 'RAssign' vector into two pieces. The first argument is a+-- phantom argument that gives the form of the first list piece.+split :: (c ~ (c1 :++: c2)) => prx c1 ->+                 RAssign any c2 -> RAssign f c -> (RAssign f c1, RAssign f c2)+split _ MNil mc = (mc, MNil)+split _ (any :>: _) (mc :>: x) = (mc1, mc2 :>: x)+  where (mc1, mc2) = split Proxy any mc++-- | Create a vector of proofs that each type in @c@ is a 'Member' of @c@.+members :: RAssign f c -> RAssign (Member c) c+members MNil = MNil+members (c :>: _) = map Member_Step (members c) :>: Member_Base++-- | A type-class which ensures that ctx is a valid context, i.e., has+-- | the form (RNil :> t1 :> ... :> tn) for some types t1 through tn+class TypeCtx ctx where+  typeCtxProxies :: RAssign Proxy ctx++instance TypeCtx RNil where+  typeCtxProxies = MNil++instance TypeCtx ctx => TypeCtx (ctx :> a) where+  typeCtxProxies = typeCtxProxies :>: Proxy