{-# LANGUAGE ScopedTypeVariables #-}
module Data.ProtoLens.Message.Enum
( messageEnumFrom
, messageEnumFromTo
, messageEnumFromThen
, messageEnumFromThenTo
) where
import Data.List (unfoldr)
import Data.Ord (comparing)
messageEnumFromTo :: Enum a => a -> a -> [a]
messageEnumFromTo :: forall a. Enum a => a -> a -> [a]
messageEnumFromTo a
start a
stop = case (a -> Int) -> a -> a -> Ordering
forall a b. Ord a => (b -> a) -> b -> b -> Ordering
comparing a -> Int
forall a. Enum a => a -> Int
fromEnum a
start a
stop of
Ordering
LT -> a -> a -> a -> [a]
forall a. Enum a => a -> a -> a -> [a]
messageEnumFromThenTo a
start (a -> a
forall a. Enum a => a -> a
succ a
start) a
stop
Ordering
EQ -> [a
start]
Ordering
GT -> []
messageEnumFrom :: (Enum a, Bounded a) => a -> [a]
messageEnumFrom :: forall a. (Enum a, Bounded a) => a -> [a]
messageEnumFrom = (a -> a -> [a]) -> a -> a -> [a]
forall a b c. (a -> b -> c) -> b -> a -> c
flip a -> a -> [a]
forall a. Enum a => a -> a -> [a]
messageEnumFromTo a
forall a. Bounded a => a
maxBound
messageEnumFromThen :: (Enum a, Bounded a) => a -> a -> [a]
messageEnumFromThen :: forall a. (Enum a, Bounded a) => a -> a -> [a]
messageEnumFromThen a
start a
step = case (a -> Int) -> a -> a -> Ordering
forall a b. Ord a => (b -> a) -> b -> b -> Ordering
comparing a -> Int
forall a. Enum a => a -> Int
fromEnum a
start a
step of
Ordering
LT -> a -> a -> a -> [a]
forall a. Enum a => a -> a -> a -> [a]
messageEnumFromThenTo a
start a
step a
forall a. Bounded a => a
maxBound
Ordering
EQ -> a -> [a]
forall a. a -> [a]
repeat a
start
Ordering
GT -> a -> a -> a -> [a]
forall a. Enum a => a -> a -> a -> [a]
messageEnumFromThenTo a
start a
step a
forall a. Bounded a => a
minBound
messageEnumFromThenTo :: forall a . Enum a => a -> a -> a -> [a]
messageEnumFromThenTo :: forall a. Enum a => a -> a -> a -> [a]
messageEnumFromThenTo a
start a
step a
stop = case (a -> Int) -> a -> a -> Ordering
forall a b. Ord a => (b -> a) -> b -> b -> Ordering
comparing a -> Int
forall a. Enum a => a -> Int
fromEnum a
start a
step of
Ordering
LT -> (a -> a) -> Ordering -> [a]
helper a -> a
forall a. Enum a => a -> a
succ Ordering
GT
Ordering
EQ -> if Int
stopInt Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
stepInt then a -> [a]
forall a. a -> [a]
repeat a
start else []
Ordering
GT -> (a -> a) -> Ordering -> [a]
helper a -> a
forall a. Enum a => a -> a
pred Ordering
LT
where
stopInt :: Int
stopInt = a -> Int
forall a. Enum a => a -> Int
fromEnum a
stop
stepInt :: Int
stepInt = a -> Int
forall a. Enum a => a -> Int
fromEnum a
step
helper :: (a -> a) -> Ordering -> [a]
helper a -> a
iter Ordering
isAfter
| (a -> Int) -> a -> a -> Ordering
forall a b. Ord a => (b -> a) -> b -> b -> Ordering
comparing a -> Int
forall a. Enum a => a -> Int
fromEnum a
start a
stop Ordering -> Ordering -> Bool
forall a. Eq a => a -> a -> Bool
== Ordering
isAfter = []
| Int -> Int -> Ordering
forall a. Ord a => a -> a -> Ordering
compare Int
stepInt Int
stopInt Ordering -> Ordering -> Bool
forall a. Eq a => a -> a -> Bool
== Ordering
isAfter = [a
start]
| Bool
otherwise = a
start a -> [a] -> [a]
forall a. a -> [a] -> [a]
: (Maybe a -> Maybe (a, Maybe a)) -> Maybe a -> [a]
forall b a. (b -> Maybe (a, b)) -> b -> [a]
unfoldr ((a -> (a, Maybe a)) -> Maybe a -> Maybe (a, Maybe a)
forall a b. (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> (a, Maybe a)
unfoldIter) (a -> Maybe a
forall a. a -> Maybe a
Just a
step)
where
jump :: t -> a -> Maybe a
jump t
0 a
a = a -> Maybe a
forall a. a -> Maybe a
Just a
a
jump t
n a
a
| Int
stopInt Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== a -> Int
forall a. Enum a => a -> Int
fromEnum a
a = Maybe a
forall a. Maybe a
Nothing
| Bool
otherwise = t -> a -> Maybe a
jump (t
nt -> t -> t
forall a. Num a => a -> a -> a
-t
1) (a -> Maybe a) -> a -> Maybe a
forall a b. (a -> b) -> a -> b
$ a -> a
iter a
a
unfoldIter :: a -> (a, Maybe a)
unfoldIter a
a = (a
a, Integer -> a -> Maybe a
forall {t}. (Eq t, Num t) => t -> a -> Maybe a
jump Integer
skipCount a
a)
countSkips :: Integer -> a -> Integer
countSkips :: Integer -> a -> Integer
countSkips Integer
n a
start'
| Int
stepInt Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== a -> Int
forall a. Enum a => a -> Int
fromEnum a
start' = Integer
n
| Bool
otherwise = Integer -> a -> Integer
countSkips (Integer
nInteger -> Integer -> Integer
forall a. Num a => a -> a -> a
+Integer
1) (a -> Integer) -> a -> Integer
forall a b. (a -> b) -> a -> b
$ a -> a
iter a
start'
skipCount :: Integer
skipCount = Integer -> a -> Integer
countSkips Integer
0 a
start