data-index-0.1.0.0: src/Data/Index.hs
{-# 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)