{-# 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 (
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
newtype NameSet k = NameSet { unNameSet :: IntSet }
data SomeName k = forall (a :: k). SomeName (Name a)
$(mkNuMatching [t| forall k. SomeName k |])
empty :: NameSet k
empty = NameSet $ IntSet.empty
singleton :: Name (a::k) -> NameSet k
singleton (MkName i) = NameSet $ IntSet.singleton $ i
fromList :: [SomeName k] -> NameSet k
fromList =
NameSet . IntSet.fromList . Prelude.map (\(SomeName (MkName i)) -> i)
toList :: NameSet k -> [SomeName k]
toList (NameSet s) = Prelude.map (SomeName . MkName) (IntSet.toList s)
insert :: Name (a::k) -> NameSet k -> NameSet k
insert (MkName i) (NameSet s) = NameSet $ IntSet.insert i s
delete :: Name (a::k) -> NameSet k -> NameSet k
delete (MkName i) (NameSet s) = NameSet $ IntSet.delete i s
member :: Name (a::k) -> NameSet k -> Bool
member (MkName i) (NameSet s) = IntSet.member i s
null :: NameSet k -> Bool
null (NameSet s) = IntSet.null s
size :: NameSet k -> Int
size (NameSet s) = IntSet.size s
union :: NameSet k -> NameSet k -> NameSet k
union (NameSet s1) (NameSet s2) = NameSet $ IntSet.union s1 s2
unions :: Foldable f => f (NameSet k) -> NameSet k
unions = Foldable.foldl' union empty
difference :: NameSet k -> NameSet k -> NameSet k
difference (NameSet s1) (NameSet s2) = NameSet $ IntSet.difference s1 s2
(\\) :: NameSet k -> NameSet k -> NameSet k
(\\) = difference
intersection :: NameSet k -> NameSet k -> NameSet k
intersection (NameSet s1) (NameSet s2) = NameSet $ IntSet.intersection s1 s2
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
foldr :: (forall (a::k). Name a -> r -> r) -> r -> NameSet k -> r
foldr f r (NameSet s) = IntSet.foldr (f . MkName) r s
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
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