algebraic-graphs-0.2: src/Algebra/Graph/Relation/InternalDerived.hs
-----------------------------------------------------------------------------
-- |
-- Module : Algebra.Graph.Relation.InternalDerived
-- Copyright : (c) Andrey Mokhov 2016-2018
-- License : MIT (see the file LICENSE)
-- Maintainer : andrey.mokhov@gmail.com
-- Stability : unstable
--
-- This module exposes the implementation of derived binary relation data types.
-- The API is unstable and unsafe, and is exposed only for documentation. You
-- should use the non-internal modules "Algebra.Graph.Relation.Reflexive",
-- "Algebra.Graph.Relation.Symmetric", "Algebra.Graph.Relation.Transitive" and
-- "Algebra.Graph.Relation.Preorder" instead.
-----------------------------------------------------------------------------
module Algebra.Graph.Relation.InternalDerived (
-- * Implementation of derived binary relations
ReflexiveRelation (..), SymmetricRelation (..), TransitiveRelation (..),
PreorderRelation (..)
) where
import Control.DeepSeq (NFData (..))
import Algebra.Graph.Class
import Algebra.Graph.Relation (Relation, reflexiveClosure, symmetricClosure,
transitiveClosure, preorderClosure)
{-| The 'ReflexiveRelation' data type represents a /reflexive binary relation/
over a set of elements. Reflexive relations satisfy all laws of the
'Reflexive' type class and, in particular, the /self-loop/ axiom:
@'vertex' x == 'vertex' x * 'vertex' x@
The 'Show' instance produces reflexively closed expressions:
@show (1 :: ReflexiveRelation Int) == "edge 1 1"
show (1 * 2 :: ReflexiveRelation Int) == "edges [(1,1),(1,2),(2,2)]"@
-}
newtype ReflexiveRelation a = ReflexiveRelation { fromReflexive :: Relation a }
deriving (Num, NFData)
instance Ord a => Eq (ReflexiveRelation a) where
x == y = reflexiveClosure (fromReflexive x) == reflexiveClosure (fromReflexive y)
instance (Ord a, Show a) => Show (ReflexiveRelation a) where
show = show . reflexiveClosure . fromReflexive
instance Ord a => Graph (ReflexiveRelation a) where
type Vertex (ReflexiveRelation a) = a
empty = ReflexiveRelation empty
vertex = ReflexiveRelation . vertex
overlay x y = ReflexiveRelation $ fromReflexive x `overlay` fromReflexive y
connect x y = ReflexiveRelation $ fromReflexive x `connect` fromReflexive y
instance Ord a => Reflexive (ReflexiveRelation a)
-- TODO: Optimise the implementation by caching the results of symmetric closure.
{-| The 'SymmetricRelation' data type represents a /symmetric binary relation/
over a set of elements. Symmetric relations satisfy all laws of the
'Undirected' type class and, in particular, the
commutativity of connect:
@'connect' x y == 'connect' y x@
The 'Show' instance produces symmetrically closed expressions:
@show (1 :: SymmetricRelation Int) == "vertex 1"
show (1 * 2 :: SymmetricRelation Int) == "edges [(1,2),(2,1)]"@
-}
newtype SymmetricRelation a = SymmetricRelation { fromSymmetric :: Relation a }
deriving (Num, NFData)
instance Ord a => Eq (SymmetricRelation a) where
x == y = symmetricClosure (fromSymmetric x) == symmetricClosure (fromSymmetric y)
instance (Ord a, Show a) => Show (SymmetricRelation a) where
show = show . symmetricClosure . fromSymmetric
-- TODO: To be derived automatically using GeneralizedNewtypeDeriving in GHC 8.2
instance Ord a => Graph (SymmetricRelation a) where
type Vertex (SymmetricRelation a) = a
empty = SymmetricRelation empty
vertex = SymmetricRelation . vertex
overlay x y = SymmetricRelation $ fromSymmetric x `overlay` fromSymmetric y
connect x y = SymmetricRelation $ fromSymmetric x `connect` fromSymmetric y
instance Ord a => Undirected (SymmetricRelation a)
-- TODO: Optimise the implementation by caching the results of transitive closure.
{-| The 'TransitiveRelation' data type represents a /transitive binary relation/
over a set of elements. Transitive relations satisfy all laws of the
'Transitive' type class and, in particular, the /closure/ axiom:
@y /= 'empty' ==> x * y + x * z + y * z == x * y + y * z@
For example, the following holds:
@'path' xs == ('clique' xs :: TransitiveRelation Int)@
The 'Show' instance produces transitively closed expressions:
@show (1 * 2 :: TransitiveRelation Int) == "edge 1 2"
show (1 * 2 + 2 * 3 :: TransitiveRelation Int) == "edges [(1,2),(1,3),(2,3)]"@
-}
newtype TransitiveRelation a = TransitiveRelation { fromTransitive :: Relation a }
deriving (Num, NFData)
instance Ord a => Eq (TransitiveRelation a) where
x == y = transitiveClosure (fromTransitive x) == transitiveClosure (fromTransitive y)
instance (Ord a, Show a) => Show (TransitiveRelation a) where
show = show . transitiveClosure . fromTransitive
-- TODO: To be derived automatically using GeneralizedNewtypeDeriving in GHC 8.2
instance Ord a => Graph (TransitiveRelation a) where
type Vertex (TransitiveRelation a) = a
empty = TransitiveRelation empty
vertex = TransitiveRelation . vertex
overlay x y = TransitiveRelation $ fromTransitive x `overlay` fromTransitive y
connect x y = TransitiveRelation $ fromTransitive x `connect` fromTransitive y
instance Ord a => Transitive (TransitiveRelation a)
-- TODO: Optimise the implementation by caching the results of preorder closure.
{-| The 'PreorderRelation' data type represents a
/binary relation that is both reflexive and transitive/. Preorders satisfy all
laws of the 'Preorder' type class and, in particular, the /self-loop/ axiom:
@'vertex' x == 'vertex' x * 'vertex' x@
and the /closure/ axiom:
@y /= 'empty' ==> x * y + x * z + y * z == x * y + y * z@
For example, the following holds:
@'path' xs == ('clique' xs :: PreorderRelation Int)@
The 'Show' instance produces reflexively and transitively closed expressions:
@show (1 :: PreorderRelation Int) == "edge 1 1"
show (1 * 2 :: PreorderRelation Int) == "edges [(1,1),(1,2),(2,2)]"
show (1 * 2 + 2 * 3 :: PreorderRelation Int) == "edges [(1,1),(1,2),(1,3),(2,2),(2,3),(3,3)]"@
-}
newtype PreorderRelation a = PreorderRelation { fromPreorder :: Relation a }
deriving (Num, NFData)
instance (Ord a, Show a) => Show (PreorderRelation a) where
show = show . preorderClosure . fromPreorder
instance Ord a => Eq (PreorderRelation a) where
x == y = preorderClosure (fromPreorder x) == preorderClosure (fromPreorder y)
-- TODO: To be derived automatically using GeneralizedNewtypeDeriving in GHC 8.2
instance Ord a => Graph (PreorderRelation a) where
type Vertex (PreorderRelation a) = a
empty = PreorderRelation empty
vertex = PreorderRelation . vertex
overlay x y = PreorderRelation $ fromPreorder x `overlay` fromPreorder y
connect x y = PreorderRelation $ fromPreorder x `connect` fromPreorder y
instance Ord a => Reflexive (PreorderRelation a)
instance Ord a => Transitive (PreorderRelation a)
instance Ord a => Preorder (PreorderRelation a)