diff options
Diffstat (limited to 'libraries/base/Data/Type/Ord.hs')
-rw-r--r-- | libraries/base/Data/Type/Ord.hs | 125 |
1 files changed, 125 insertions, 0 deletions
diff --git a/libraries/base/Data/Type/Ord.hs b/libraries/base/Data/Type/Ord.hs new file mode 100644 index 0000000000..d882a82a61 --- /dev/null +++ b/libraries/base/Data/Type/Ord.hs @@ -0,0 +1,125 @@ +{-# LANGUAGE ConstraintKinds #-} +{-# LANGUAGE DataKinds #-} +{-# LANGUAGE GADTs #-} +{-# LANGUAGE NoImplicitPrelude #-} +{-# LANGUAGE PolyKinds #-} +{-# LANGUAGE Safe #-} +{-# LANGUAGE StandaloneDeriving #-} +{-# LANGUAGE StandaloneKindSignatures #-} +{-# LANGUAGE TypeFamilies #-} +{-# LANGUAGE TypeOperators #-} +{-# LANGUAGE UndecidableInstances #-} + +----------------------------------------------------------------------------- +-- | +-- Module : Data.Type.Ord +-- License : BSD-style (see the LICENSE file in the distribution) +-- +-- Maintainer : libraries@haskell.org +-- Stability : experimental +-- Portability : not portable +-- +-- Basic operations on type-level Orderings. +-- +-- @since 4.16.0.0 +----------------------------------------------------------------------------- + +module Data.Type.Ord ( + Compare, OrderingI(..) + , type (<=), type (<=?) + , type (>=), type (>=?) + , type (>), type (>?) + , type (<), type (<?) + , Max, Min + , OrdCond + ) where + +import GHC.Show(Show(..)) +import GHC.TypeLits.Internal +import GHC.TypeNats.Internal +import Data.Bool +import Data.Char(Char) +import Data.Eq +import Data.Ord + +-- | 'Compare' branches on the kind of its arguments to either compare by +-- 'Symbol' or 'Nat'. +-- @since 4.16.0.0 +type Compare :: k -> k -> Ordering +type family Compare a b + +type instance Compare (a :: Natural) b = CmpNat a b +type instance Compare (a :: Symbol) b = CmpSymbol a b +type instance Compare (a :: Char) b = CmpChar a b + +-- | Ordering data type for type literals that provides proof of their ordering. +-- @since 4.16.0.0 +data OrderingI a b where + LTI :: Compare a b ~ 'LT => OrderingI a b + EQI :: Compare a a ~ 'EQ => OrderingI a a + GTI :: Compare a b ~ 'GT => OrderingI a b + +deriving instance Show (OrderingI a b) +deriving instance Eq (OrderingI a b) + + +infix 4 <=?, <=, >=?, >=, <?, <, >?, > + +-- | Comparison (<=) of comparable types, as a constraint. +-- @since 4.16.0.0 +type x <= y = (x <=? y) ~ 'True + +-- | Comparison (>=) of comparable types, as a constraint. +-- @since 4.16.0.0 +type x >= y = (x >=? y) ~ 'True + +-- | Comparison (<) of comparable types, as a constraint. +-- @since 4.16.0.0 +type x < y = (x >? y) ~ 'True + +-- | Comparison (>) of comparable types, as a constraint. +-- @since 4.16.0.0 +type x > y = (x >? y) ~ 'True + + +-- | Comparison (<=) of comparable types, as a function. +-- @since 4.16.0.0 +type (<=?) :: k -> k -> Bool +type m <=? n = OrdCond (Compare m n) 'True 'True 'False + +-- | Comparison (>=) of comparable types, as a function. +-- @since 4.16.0.0 +type (>=?) :: k -> k -> Bool +type m >=? n = OrdCond (Compare m n) 'False 'True 'True + +-- | Comparison (<) of comparable types, as a function. +-- @since 4.16.0.0 +type (<?) :: k -> k -> Bool +type m <? n = OrdCond (Compare m n) 'True 'False 'False + +-- | Comparison (>) of comparable types, as a function. +-- @since 4.16.0.0 +type (>?) :: k -> k -> Bool +type m >? n = OrdCond (Compare m n) 'False 'False 'True + + +-- | Maximum between two comparable types. +-- @since 4.16.0.0 +type Max :: k -> k -> k +type Max m n = OrdCond (Compare m n) n n m + +-- | Minimum between two comparable types. +-- @since 4.16.0.0 +type Min :: k -> k -> k +type Min m n = OrdCond (Compare m n) m m n + + +-- | A case statement on `Ordering`. +-- `Ordering c l e g` is `l` when `c ~ LT`, `e` when `c ~ EQ`, and `g` when +-- `c ~ GT`. +-- @since 4.16.0.0 +type OrdCond :: Ordering -> k -> k -> k -> k +type family OrdCond o lt eq gt where + OrdCond 'LT lt eq gt = lt + OrdCond 'EQ lt eq gt = eq + OrdCond 'GT lt eq gt = gt |