{-| Module : WebApi.Versioning License : BSD3 Stability : experimental -} {-# LANGUAGE DataKinds #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE KindSignatures #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE PolyKinds #-} {-# LANGUAGE TypeFamilies #-} module WebApi.Versioning ( -- * Versioning styles MajorMinor (..) , Major (..) -- * Building custom versions , OrdVersion (..) , VersionOrd , compareVersion ) where import Data.Proxy import GHC.TypeLits -- | Comparison between versions. class OrdVersion (ver :: *) where cmpVersion :: (ver ~ ((proxy :: k -> *) (v1 :: k)), ord ~ (VersionOrd (proxy v1) (proxy v2)), SingOrd ord) => proxy v1 -> proxy (v2 :: k) -> Proxy ord cmpVersion _ _ = (Proxy :: Proxy ord) -- | Singleton class for ordering class SingOrd (ord :: Ordering) where singOrd :: proxy ord -> Ordering instance SingOrd 'EQ where singOrd = const EQ instance SingOrd 'LT where singOrd = const LT instance SingOrd 'GT where singOrd = const GT -- | Defines ordering of versions. type family VersionOrd (v1 :: k) (v2 :: k) :: Ordering -- | Comparison between two versions. Returns an 'Ord'. -- -- >>> compareVersion (MajorMinor :: MajorMinor (0, 0)) (MajorMinor :: MajorMinor (0, 1)) == LT -- True compareVersion :: (OrdVersion (proxy v1), SingOrd (VersionOrd (proxy v1) (proxy v2))) => proxy (v1 :: k) -> proxy (v2 :: k) -> Ordering compareVersion v1 v2 = singOrd $ cmpVersion v1 v2 -- | A Style of versioning which has a Major version and a Minor version. data MajorMinor (ver :: (Nat, Nat)) = MajorMinor -- | A Style of versioning which has only has a Major version. data Major (maj :: Nat) = Major type instance VersionOrd (Major (m :: Nat)) (Major (n :: Nat)) = (CmpNat m n) type instance VersionOrd (MajorMinor '(maj1, min1)) (MajorMinor '(maj2, min2)) = 'EQ instance OrdVersion (Major maj) where instance OrdVersion (MajorMinor '(maj, min)) where