{-# LANGUAGE ConstraintKinds #-} {-# LANGUAGE FunctionalDependencies #-} {-# LANGUAGE PolyKinds #-} {-# LANGUAGE QuantifiedConstraints #-} {-# LANGUAGE UndecidableInstances #-} {-| Module : Data.JoinSemilattice.Class.Mapping Description : Lift "regular functions" over parameter types. Copyright : (c) Tom Harding, 2020 License : MIT -} module Data.JoinSemilattice.Class.Mapping where import Data.JoinSemilattice.Class.Merge (Merge) import Data.JoinSemilattice.Defined (Defined (..)) import Data.JoinSemilattice.Intersect (Intersect, Intersectable) import qualified Data.JoinSemilattice.Intersect as Intersect import Data.Kind (Constraint, Type) -- | Lift a relationship between two values over some type constructor. -- Typically, this type constructor will be the parameter type. class (forall x. c x => Merge (f x)) => Mapping (f :: Type -> Type) (c :: Type -> Constraint) | f -> c where mapR :: (c x, c y) => (Maybe (x -> y), Maybe (y -> x)) -> ((f x, f y) -> (f x, f y)) instance Mapping Defined Eq where mapR ( fs, gs ) ( xs, ys ) = ( case ys of Unknown -> Unknown Conflict -> Conflict Exactly y -> case gs of Just g -> Exactly (g y) Nothing -> Unknown , case xs of Unknown -> Unknown Conflict -> Conflict Exactly x -> case fs of Just f -> Exactly (f x) Nothing -> Unknown ) instance Mapping Intersect Intersectable where mapR ( fs, gs ) ( xs, ys ) = ( case gs of Just g -> Intersect.map g ys Nothing -> mempty , case fs of Just f -> Intersect.map f xs Nothing -> mempty )