{-# LANGUAGE DataKinds #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UndecidableInstances #-}

module Composite.Fcf
  ( FromCompositeS,
    FromComposite,
    ToCompositeS,
    ToComposite,
    Union,
    Difference,
    Intersection,
  )
where

import Composite.Record
import Data.Kind
import Fcf
import qualified Fcf.Data.MapC
import GHC.TypeLits

data FromCompositeS :: Type -> Exp (Symbol, Type)

type instance Eval (FromCompositeS (s :-> x)) = '(s, x)

data FromComposite :: [Type] -> Exp (Fcf.Data.MapC.MapC Symbol Type)

type instance Eval (FromComposite x) = Eval (Fcf.Data.MapC.FromList =<< Fcf.Map FromCompositeS x)

data ToCompositeS :: (Symbol, Type) -> Exp Type

type instance Eval (ToCompositeS '(s, x)) = s :-> x

data ToComposite :: Fcf.Data.MapC.MapC Symbol Type -> Exp [Type]

type instance Eval (ToComposite x) = Eval (Fcf.Map ToCompositeS =<< Fcf.Data.MapC.ToList x)

data Difference :: [Type] -> [Type] -> Exp [Type]

type instance Eval (Difference xs ys) = Eval (ToComposite =<< Fcf.Data.MapC.Difference (Eval (FromComposite xs)) (Eval (FromComposite ys)))

data Union :: [Type] -> [Type] -> Exp [Type]

type instance Eval (Union xs ys) = Eval (ToComposite =<< Fcf.Data.MapC.Union (Eval (FromComposite xs)) (Eval (FromComposite ys)))

data Intersection :: [Type] -> [Type] -> Exp [Type]

type instance Eval (Intersection xs ys) = Eval (ToComposite =<< Fcf.Data.MapC.Intersection (Eval (FromComposite xs)) (Eval (FromComposite ys)))