summaryrefslogtreecommitdiff
path: root/libraries/base/Data/Ord.hs
diff options
context:
space:
mode:
Diffstat (limited to 'libraries/base/Data/Ord.hs')
-rw-r--r--libraries/base/Data/Ord.hs24
1 files changed, 22 insertions, 2 deletions
diff --git a/libraries/base/Data/Ord.hs b/libraries/base/Data/Ord.hs
index b21acb8e33..779e1b69d0 100644
--- a/libraries/base/Data/Ord.hs
+++ b/libraries/base/Data/Ord.hs
@@ -24,11 +24,11 @@ module Data.Ord (
clamp,
) where
-import Data.Bits (Bits, FiniteBits)
+import Data.Bits (Bits, FiniteBits, complement)
import Foreign.Storable (Storable)
import GHC.Ix (Ix)
import GHC.Base
-import GHC.Enum (Bounded(..))
+import GHC.Enum (Bounded(..), Enum(..))
import GHC.Float (Floating, RealFloat)
import GHC.Num
import GHC.Read
@@ -146,6 +146,26 @@ instance Bounded a => Bounded (Down a) where
minBound = Down maxBound
maxBound = Down minBound
+-- | Swaps @'succ'@ and @'pred'@ of the underlying type.
+--
+-- @since 4.18.0.0
+instance (Enum a, Bounded a, Eq a) => Enum (Down a) where
+ succ = fmap pred
+ pred = fmap succ
+
+ -- Here we use the fact that 'comparing (complement @Int)' behaves
+ -- as an order-swapping `compare @Int`.
+ fromEnum = complement . fromEnum . getDown
+ toEnum = Down . toEnum . complement
+
+ enumFrom (Down x)
+ | x == minBound
+ = [Down x] -- We can't rely on 'enumFromThen _ (pred @a minBound)` behaving nicely,
+ -- since 'enumFromThen _' might be strict and 'pred minBound' might throw
+ | otherwise
+ = coerce $ enumFromThen x (pred x)
+ enumFromThen (Down x) (Down y) = coerce $ enumFromThen x y
+
-- | @since 4.11.0.0
instance Functor Down where
fmap = coerce