{-# 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 forall a b. Ord a => (b -> a) -> b -> b -> Ordering
comparing forall a. Enum a => a -> Int
fromEnum a
start a
stop of
Ordering
LT -> forall a. Enum a => a -> a -> a -> [a]
messageEnumFromThenTo a
start (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 = forall a b c. (a -> b -> c) -> b -> a -> c
flip forall a. Enum a => a -> a -> [a]
messageEnumFromTo 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 forall a b. Ord a => (b -> a) -> b -> b -> Ordering
comparing forall a. Enum a => a -> Int
fromEnum a
start a
step of
Ordering
LT -> forall a. Enum a => a -> a -> a -> [a]
messageEnumFromThenTo a
start a
step forall a. Bounded a => a
maxBound
Ordering
EQ -> forall a. a -> [a]
repeat a
start
Ordering
GT -> forall a. Enum a => a -> a -> a -> [a]
messageEnumFromThenTo a
start a
step 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 forall a b. Ord a => (b -> a) -> b -> b -> Ordering
comparing forall a. Enum a => a -> Int
fromEnum a
start a
step of
Ordering
LT -> (a -> a) -> Ordering -> [a]
helper forall a. Enum a => a -> a
succ Ordering
GT
Ordering
EQ -> if Int
stopInt forall a. Ord a => a -> a -> Bool
>= Int
stepInt then forall a. a -> [a]
repeat a
start else []
Ordering
GT -> (a -> a) -> Ordering -> [a]
helper forall a. Enum a => a -> a
pred Ordering
LT
where
stopInt :: Int
stopInt = forall a. Enum a => a -> Int
fromEnum a
stop
stepInt :: Int
stepInt = forall a. Enum a => a -> Int
fromEnum a
step
helper :: (a -> a) -> Ordering -> [a]
helper a -> a
iter Ordering
isAfter
| forall a b. Ord a => (b -> a) -> b -> b -> Ordering
comparing forall a. Enum a => a -> Int
fromEnum a
start a
stop forall a. Eq a => a -> a -> Bool
== Ordering
isAfter = []
| forall a. Ord a => a -> a -> Ordering
compare Int
stepInt Int
stopInt forall a. Eq a => a -> a -> Bool
== Ordering
isAfter = [a
start]
| Bool
otherwise = a
start forall a. a -> [a] -> [a]
: forall b a. (b -> Maybe (a, b)) -> b -> [a]
unfoldr (forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> (a, Maybe a)
unfoldIter) (forall a. a -> Maybe a
Just a
step)
where
jump :: t -> a -> Maybe a
jump t
0 a
a = forall a. a -> Maybe a
Just a
a
jump t
n a
a
| Int
stopInt forall a. Eq a => a -> a -> Bool
== forall a. Enum a => a -> Int
fromEnum a
a = forall a. Maybe a
Nothing
| Bool
otherwise = t -> a -> Maybe a
jump (t
nforall a. Num a => a -> a -> a
-t
1) forall a b. (a -> b) -> a -> b
$ a -> a
iter a
a
unfoldIter :: a -> (a, Maybe a)
unfoldIter a
a = (a
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 forall a. Eq a => a -> a -> Bool
== forall a. Enum a => a -> Int
fromEnum a
start' = Integer
n
| Bool
otherwise = Integer -> a -> Integer
countSkips (Integer
nforall a. Num a => a -> a -> a
+Integer
1) forall a b. (a -> b) -> a -> b
$ a -> a
iter a
start'
skipCount :: Integer
skipCount = Integer -> a -> Integer
countSkips Integer
0 a
start