packages feed

fcf-composite-0.1.1.0: src/Composite/Fcf.hs

{-# 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)