{-# LANGUAGE Rank2Types #-} -- | 'Index', necessary instances for it, 'end' and 'mid' for any container module Data.Index where import Control.Applicative import Control.Monad -- | This type can contain any container-independent values to be indexed with newtype Index t i = Index {runIndex :: forall a . t a -> i} -- | Flipped version of 'runIndex' run :: t a -> Index t i -> i run = flip runIndex -- | Reader-like Monad instance instance Monad (Index t) where idx >>= f = Index $ \t -> run t $ f $ run t idx -- | Reader-like Applicative instance instance Applicative (Index t) where pure i = Index (const i) (<*>) = ap -- | Reader-like Functor instance instance Functor (Index t) where fmap = ap . return -- | Num instance is done via 'liftA2' and 'pure' instance Num i => Num (Index t i) where (+) = liftA2 (+) (-) = liftA2 (-) (*) = liftA2 (*) abs = liftA abs signum = liftA signum fromInteger = pure . fromInteger -- | The end of any linear container end :: Foldable t => Index t Int end = Index (\t -> length t - 1) -- | The middle of any linear container mid :: Foldable t => Index t Int mid = Index (\t -> length t `div` 2)