fcf-graphs-0.0.1.0: src/Fcf/Data/Graph.hs
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UndecidableInstances #-}
module Fcf.Data.Graph where
import Fcf hiding (Map)
import qualified Fcf.Data.AdjacencyMap as AM
import Fcf.Data.Nat
import qualified Fcf.Data.Set as S
data Graph a where
Empty :: Graph a
Vertex :: a -> Graph a
Overlay :: Graph a -> Graph a -> Graph a
Connect :: Graph a -> Graph a -> Graph a
-- | Empty
--
-- === __Example__
--
-- >>> :kind! (Eval Empty :: Graph Nat)
-- (Eval Empty :: Graph Nat) :: Graph Nat
-- = 'Empty
data Empty :: Exp (Graph a)
type instance Eval Empty = 'Empty
-- | Vertex
--
-- === __Example__
--
-- >>> :kind! (Eval (Vertex 1) :: Graph Nat)
-- (Eval (Vertex 1) :: Graph Nat) :: Graph Nat
-- = 'Vertex 1
data Vertex :: a -> Exp (Graph a)
type instance Eval (Vertex a) = 'Vertex a
-- | Edge
--
-- === __Example__
--
-- >>> :kind! (Eval (Edge 1 2) :: Graph Nat)
-- (Eval (Edge 1 2) :: Graph Nat) :: Graph Nat
-- = 'Connect ('Vertex 1) ('Vertex 2)
data Edge :: a -> a -> Exp (Graph a)
type instance Eval (Edge x y) = 'Connect ('Vertex x) ('Vertex y)
-- | Overlay
--
-- === __Example__
--
-- >>> :kind! (Eval (Overlay ('Vertex 1) ('Vertex 2)) :: Graph Nat)
-- (Eval (Overlay ('Vertex 1) ('Vertex 2)) :: Graph Nat) :: Graph Nat
-- = 'Overlay ('Vertex 1) ('Vertex 2)
data Overlay :: Graph a -> Graph a -> Exp (Graph a)
type instance Eval (Overlay x y) = 'Overlay x y
-- | Connect
--
-- === __Example__
--
-- >>> :kind! (Eval (Connect ('Vertex 1) ('Vertex 2)) :: Graph Nat)
-- (Eval (Connect ('Vertex 1) ('Vertex 2)) :: Graph Nat) :: Graph Nat
-- = 'Connect ('Vertex 1) ('Vertex 2)
data Connect :: Graph a -> Graph a -> Exp (Graph a)
type instance Eval (Connect x y) = 'Connect x y
-- | Map
--
-- === __Example__
--
-- >>> :kind! Eval (Map ((+) 1) =<< Connect ('Overlay ('Vertex 1) ('Vertex 2)) ('Vertex 3))
-- Eval (Map ((+) 1) =<< Connect ('Overlay ('Vertex 1) ('Vertex 2)) ('Vertex 3)) :: Graph
-- Nat
-- = 'Connect ('Overlay ('Vertex 2) ('Vertex 3)) ('Vertex 4)
data Map :: (a -> Exp b) -> Graph a -> Exp (Graph b)
type instance Eval (Map _ 'Empty) = 'Empty
type instance Eval (Map f ('Vertex a)) = 'Vertex (Eval (f $ a))
type instance Eval (Map f ('Overlay x y)) = 'Overlay (Eval (Map f x)) (Eval (Map f y))
type instance Eval (Map f ('Connect x y)) = 'Connect (Eval (Map f x)) (Eval (Map f y))
-- | Foldg
--
-- === __Example__
--
-- >>> :kind! Eval (FoldG (Pure 0) Pure (+) (+) =<< Connect ('Overlay ('Vertex 1) ('Vertex 2)) ('Vertex 3))
-- Eval (FoldG (Pure 0) Pure (+) (+) =<< Connect ('Overlay ('Vertex 1) ('Vertex 2)) ('Vertex 3)) :: Nat
-- = 6
data FoldG :: Exp b -> (a -> Exp b) -> (b -> b -> Exp b) -> (b -> b -> Exp b) -> Graph a -> Exp b
type instance Eval (FoldG e _ _ _ 'Empty) = Eval e
type instance Eval (FoldG _ v _ _ ('Vertex x)) = Eval (v x)
type instance Eval (FoldG e v o c ('Overlay x y)) = Eval (o (Eval (FoldG e v o c x)) (Eval (FoldG e v o c y)))
type instance Eval (FoldG e v o c ('Connect x y)) = Eval (c (Eval (FoldG e v o c x)) (Eval (FoldG e v o c y)))
-- | ToAdjacencyMap
--
-- === __Example__
-- >>> :kind! Eval (ToAdjacencyMap (Eval (Edge 1 2)))
-- Eval (ToAdjacencyMap (Eval (Edge 1 2))) :: AM.AdjacencyMap Nat
-- = 'AM.AM
-- ('Fcf.Data.MapC.MapC '[ '(1, 'S.Set '[2]), '(2, 'S.Set '[])])
data ToAdjacencyMap :: Graph a -> Exp (AM.AdjacencyMap a)
type instance Eval (ToAdjacencyMap x) = Eval (FoldG AM.Empty AM.Vertex AM.Overlay AM.Connect x)
-- | EqR
--
-- === __Example__
-- >>> :kind! Eval (EqR (Eval (Edge 1 3)) (Eval (Edge 1 2)))
-- Eval (EqR (Eval (Edge 1 3)) (Eval (Edge 1 2))) :: Bool
-- = 'False
data EqR :: Graph a -> Graph a -> Exp Bool
type instance Eval (EqR x y) = Eval (TyEq (Eval (ToAdjacencyMap x)) (Eval (ToAdjacencyMap y)))
-- | Size
--
-- === __Example__
--
-- >>> :kind! Eval (Size =<< Connect ('Overlay ('Vertex 1) ('Vertex 2)) ('Vertex 3))
-- Eval (Size =<< Connect ('Overlay ('Vertex 1) ('Vertex 2)) ('Vertex 3)) :: Nat
-- = 3
data Size :: Graph a -> Exp Nat
type instance Eval (Size g) = Eval (FoldG (Pure 1) (ConstFn 1) (+) (+) g)
-- | HasVertex
--
-- === __Example__
--
-- >>> :kind! Eval (HasVertex 3 =<< Connect ('Overlay ('Vertex 1) ('Vertex 2)) ('Vertex 3))
-- Eval (HasVertex 3 =<< Connect ('Overlay ('Vertex 1) ('Vertex 2)) ('Vertex 3)) :: Bool
-- = 'True
data HasVertex :: a -> Graph a -> Exp Bool
type instance Eval (HasVertex x g) = Eval (FoldG (Pure 'False) (TyEq x) (||) (||) g)
-- | VertexSet
--
-- === __Example__
--
-- >>> :kind! Eval (VertexSet =<< Connect ('Overlay ('Vertex 1) ('Vertex 2)) ('Vertex 3))
-- Eval (VertexSet =<< Connect ('Overlay ('Vertex 1) ('Vertex 2)) ('Vertex 3)) :: S.Set
-- Nat
-- = 'S.Set '[3, 2, 1]
data VertexSet :: Graph a -> Exp (S.Set a)
type instance Eval (VertexSet g) = Eval (FoldG S.Empty S.Singleton S.Union S.Union g)
-- | Simplify
--
-- === __Example__
--
-- >>> :kind! Eval (Simplify =<< Overlay ('Vertex 1) ('Overlay ('Vertex 2) ('Vertex 1)))
-- Eval (Simplify =<< Overlay ('Vertex 1) ('Overlay ('Vertex 2) ('Vertex 1))) :: Graph
-- Nat
-- = 'Overlay ('Vertex 2) ('Vertex 1)
data Simplify :: Graph a -> Exp (Graph a)
type instance Eval (Simplify x) = Eval (FoldG Empty Vertex (Simple Overlay) (Simple Connect) x)
data Simple :: (Graph a -> Graph a -> Exp (Graph a)) -> Graph a -> Graph a -> Exp (Graph a)
type instance Eval (Simple f x y) = Eval (Simple' x y (Eval (f x y)))
data Simple' :: Graph a -> Graph a -> Graph a -> Exp (Graph a)
type instance
Eval (Simple' x y z) =
If (Eval (EqR x z)) x (If (Eval (EqR y z)) y z)