{-# LANGUAGE Rank2Types #-}
module Data.Index where
import Control.Applicative
import Control.Monad
newtype Index t i = Index {runIndex :: forall a . t a -> i}
run :: t a -> Index t i -> i
run = flip runIndex
instance Monad (Index t) where
idx >>= f = Index $ \t -> run t $ f $ run t idx
instance Applicative (Index t) where
pure i = Index (const i)
(<*>) = ap
instance Functor (Index t) where
fmap = ap . return
instance Num i => Num (Index t i) where
(+) = liftA2 (+)
(-) = liftA2 (-)
(*) = liftA2 (*)
abs = liftA abs
signum = liftA signum
fromInteger = pure . fromInteger
end :: Foldable t => Index t Int
end = Index (\t -> length t - 1)
mid :: Foldable t => Index t Int
mid = Index (\t -> length t `div` 2)