{-# LANGUAGE FunctionalDependencies #-}
module Control.CanAquire(
runAcquire
, CanAquire(..)
, HasIndex(..)
, replaceByIndex, labelWithIndex
, I
) where
import Control.Monad.ST.Strict
import Control.Monad.State.Strict
import Data.Reflection
import qualified Data.Vector as V
import qualified Data.Vector.Mutable as MV
runAcquire :: forall t a b. Traversable t
=> (forall i. CanAquire i a => t i -> b)
-> t a -> b
runAcquire alg pts = reify v $ \px -> alg (coerceTS px ts)
where
(v,ts) = replaceByIndex pts
coerceTS :: proxy s -> t Int -> t (I s a)
coerceTS _ = fmap I
class HasIndex i Int => CanAquire i a where
aquire :: i -> a
class HasIndex t i | t -> i where
indexOf :: t -> i
replaceByIndex :: forall t a. Traversable t => t a -> (V.Vector a, t Int)
replaceByIndex ts' = runST $ do
v <- MV.new n
t <- traverse (lbl v) ts
(,t) <$> V.unsafeFreeze v
where
(ts, n) = labelWithIndex ts'
lbl :: MV.MVector s' a -> (Int,a) -> ST s' Int
lbl v (i,x) = MV.write v i x >> pure i
labelWithIndex :: Traversable t => t a -> (t (Int, a), Int)
labelWithIndex = flip runState 0 . traverse lbl
where
lbl :: a -> State Int (Int,a)
lbl x = do i <- get
put $ i+1
pure (i,x)
newtype I s a = I Int deriving (Eq, Ord, Enum)
instance Show (I s a) where
showsPrec i (I j) = showsPrec i j
instance HasIndex (I s a) Int where
indexOf (I i) = i
instance Reifies s (V.Vector a) => (I s a) `CanAquire` a where
aquire (I i) = let v = reflect @s undefined in v V.! i