    module Data.Key(
        Key, keyPair, toKey, fromKey,
        sortKeys, sortWith
        ) where

    import Data.List
    import General.Code

    data Key k v = Key k v

    instance Eq k => Eq (Key k v) where
        Key k1 v1 == Key k2 v2 = k1 == k2

    instance Ord k => Ord (Key k v) where
        compare (Key k1 v1) (Key k2 v2) = compare k1 k2

    keyPair :: k -> v -> Key k v
    keyPair = Key

    toKey :: (v -> k) -> v -> Key k v
    toKey f v = Key (f v) v

    fromKey :: Key k v -> v
    fromKey (Key k v) = v

    sortKeys :: Ord k => [Key k v] -> [v]
    sortKeys = map fromKey . sort

    -- | @sort f == sortBy (compare `on` f)@
    --   but @f@ will only be applied to each element once
    sortWith :: Ord k => (v -> k) -> [v] -> [v]
    sortWith f = sortKeys . map (toKey f)