{- |
Implementations of 'Ix' methods in terms of 'Enum' methods.

For a type @T@ of class 'Enum' you can easily define an 'Ix' instance
by copying the following code into your module:

>import qualified Data.Ix.Enum as IxEnum
>
>instance Ix T where
>   range           = IxEnum.range
>   index           = IxEnum.index
>   inRange         = IxEnum.inRange
>   rangeSize       = IxEnum.rangeSize
>   unsafeIndex     = IxEnum.unsafeIndex
>   unsafeRangeSize = IxEnum.unsafeRangeSize

-}
module Data.Ix.Enum where

import qualified Data.Ix as Ix
import qualified GHC.Arr as Arr

{-# INLINE range #-}
{-# INLINE index #-}
{-# INLINE unsafeIndex #-}
{-# INLINE inRange #-}
{-# INLINE rangeSize #-}
{-# INLINE unsafeRangeSize #-}

{- |
>>> range ('x','z')
"xyz"
>>> range (LT,GT)
[LT,EQ,GT]
-}
range :: Enum a => (a, a) -> [a]

{- |
>>> index ('a','z') 'e'
4
-}
index :: Enum a => (a, a) -> a -> Int

{- |
>>> unsafeIndex ('a','z') 'e'
4
-}
unsafeIndex :: Enum a => (a, a) -> a -> Int

{- |
>>> inRange ('a','z') 'e'
True
>>> inRange ('x','z') 'a'
False
-}
inRange :: Enum a => (a, a) -> a -> Bool

{- |
>>> rangeSize ('x','z')
3
-}
rangeSize :: Enum a => (a, a) -> Int

{- |
>>> unsafeRangeSize ('x','z')
3
-}
unsafeRangeSize :: Enum a => (a, a) -> Int

range :: forall a. Enum a => (a, a) -> [a]
range (a
l,a
r) = (Int -> a) -> [Int] -> [a]
forall a b. (a -> b) -> [a] -> [b]
map Int -> a
forall a. Enum a => Int -> a
toEnum ([Int] -> [a]) -> [Int] -> [a]
forall a b. (a -> b) -> a -> b
$ (Int, Int) -> [Int]
forall a. Ix a => (a, a) -> [a]
Ix.range (a -> Int
forall a. Enum a => a -> Int
fromEnum a
l, a -> Int
forall a. Enum a => a -> Int
fromEnum a
r)
index :: forall a. Enum a => (a, a) -> a -> Int
index (a
l,a
r) a
i = (Int, Int) -> Int -> Int
forall a. Ix a => (a, a) -> a -> Int
Ix.index (a -> Int
forall a. Enum a => a -> Int
fromEnum a
l, a -> Int
forall a. Enum a => a -> Int
fromEnum a
r) (a -> Int
forall a. Enum a => a -> Int
fromEnum a
i)
unsafeIndex :: forall a. Enum a => (a, a) -> a -> Int
unsafeIndex (a
l,a
r) a
i = (Int, Int) -> Int -> Int
forall a. Ix a => (a, a) -> a -> Int
Arr.unsafeIndex (a -> Int
forall a. Enum a => a -> Int
fromEnum a
l, a -> Int
forall a. Enum a => a -> Int
fromEnum a
r) (a -> Int
forall a. Enum a => a -> Int
fromEnum a
i)
inRange :: forall a. Enum a => (a, a) -> a -> Bool
inRange (a
l,a
r) a
i = (Int, Int) -> Int -> Bool
forall a. Ix a => (a, a) -> a -> Bool
Ix.inRange (a -> Int
forall a. Enum a => a -> Int
fromEnum a
l, a -> Int
forall a. Enum a => a -> Int
fromEnum a
r) (a -> Int
forall a. Enum a => a -> Int
fromEnum a
i)
rangeSize :: forall a. Enum a => (a, a) -> Int
rangeSize (a
l,a
r) = (Int, Int) -> Int
forall a. Ix a => (a, a) -> Int
Ix.rangeSize (a -> Int
forall a. Enum a => a -> Int
fromEnum a
l, a -> Int
forall a. Enum a => a -> Int
fromEnum a
r)
unsafeRangeSize :: forall a. Enum a => (a, a) -> Int
unsafeRangeSize (a
l,a
r) = (Int, Int) -> Int
forall a. Ix a => (a, a) -> Int
Arr.unsafeRangeSize (a -> Int
forall a. Enum a => a -> Int
fromEnum a
l, a -> Int
forall a. Enum a => a -> Int
fromEnum a
r)