{-# LANGUAGE DataKinds #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE RankNTypes #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeApplications #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE TypeOperators #-} {-# LANGUAGE UndecidableInstances #-} module Composite.Fcf ( FromCompositeS, FromComposite, ToCompositeS, ToComposite, Union, Difference, Intersection, difference, union, intersection, ) where import Composite.Record import Data.Kind import Data.Vinyl import Data.Vinyl.Lens import Data.Vinyl.TypeLevel as V import Fcf import qualified Fcf.Data.MapC import GHC.TypeLits -- | Turn a single `s :-> a` into an `'(s, a)` -- -- @since 0.1.0.0 data FromCompositeS :: Type -> Exp (Symbol, Type) type instance Eval (FromCompositeS (s :-> x)) = '(s, x) -- | Turn a list of `(s -> a)` into a `MapC s a` -- -- @since 0.1.0.0 data FromComposite :: [Type] -> Exp (Fcf.Data.MapC.MapC Symbol Type) type instance Eval (FromComposite x) = Eval (Fcf.Data.MapC.FromList =<< Fcf.Map FromCompositeS x) -- | Turn a single `(s, a)` into a `s :-> a` -- -- @since 0.1.0.0 data ToCompositeS :: (Symbol, Type) -> Exp Type type instance Eval (ToCompositeS '(s, x)) = s :-> x -- | Turn a `MapC s a` into a list of `(s :-> a)` -- -- @since 0.1.0.0 data ToComposite :: Fcf.Data.MapC.MapC Symbol Type -> Exp [Type] type instance Eval (ToComposite x) = Eval (Fcf.Map ToCompositeS =<< Fcf.Data.MapC.ToList x) -- | Difference -- -- @since 0.1.0.0 data Difference :: [Type] -> [Type] -> Exp [Type] type instance Eval (Difference xs ys) = Eval (ToComposite =<< Fcf.Data.MapC.Difference (Eval (FromComposite xs)) (Eval (FromComposite ys))) -- | Difference -- -- @since 0.1.0.0 data Union :: [Type] -> [Type] -> Exp [Type] type instance Eval (Union xs ys) = Eval (ToComposite =<< Fcf.Data.MapC.Union (Eval (FromComposite xs)) (Eval (FromComposite ys))) -- | Intersection -- -- @since 0.1.0.0 data Intersection :: [Type] -> [Type] -> Exp [Type] type instance Eval (Intersection xs ys) = Eval (ToComposite =<< Fcf.Data.MapC.Intersection (Eval (FromComposite xs)) (Eval (FromComposite ys))) -- | Take the difference of two records by casting to the result of `Difference`. -- -- @since 0.1.1.0 difference :: forall f xs ys zs. ( zs ~ Eval (Difference xs ys), zs ⊆ (xs V.++ ys) ) => Rec f xs -> Rec f ys -> Rec f zs difference x y = rcast @zs (x <+> y) -- | Take the union of two records by casting to the result of `Union`. -- -- @since 0.1.1.0 union :: forall f xs ys zs. ( zs ~ Eval (Union xs ys), zs ⊆ (xs V.++ ys) ) => Rec f xs -> Rec f ys -> Rec f zs union x y = rcast @zs (x <+> y) -- | Take the intersection of two records by casting to the result of `Intersection`. -- -- @since 0.1.1.0 intersection :: forall f xs ys zs. ( zs ~ Eval (Intersection xs ys), zs ⊆ (xs V.++ ys) ) => Rec f xs -> Rec f ys -> Rec f zs intersection x y = rcast @zs (x <+> y)