Safe Haskell | None |
---|---|
Language | Haskell2010 |
- data EdgeValue from to = Edge
- data EdgeKind = forall from to . EdgeType from to
- type family Deducible x :: Constraint
- type family Excluding x xs :: Constraint
- type family Lookup index map :: Maybe k2
- type family x =/= y :: Constraint
- class Acceptable a oldLoops unique
- type family PrependIfElem test a xs :: [k]
- type family DisallowIn new oldLoops keyFound :: [(Symbol, [Symbol])]
- data EdgeSchema edges nearLoops unique where
- ENil :: EdgeSchema [] [] unique
- ECons :: (Acceptable b oldLoops unique, EdgeValue from to ~ a, EdgeType from to ~ b, DisallowIn b oldLoops False ~ c) => !a -> EdgeSchema old oldLoops unique -> EdgeSchema (b : old) c unique
- unique :: EdgeSchema [] [] True
- notUnique :: EdgeSchema [] [] False
- data Tree a = Node a [Tree a]
- type family AppendIfNotElemTrees c trees :: [Tree k]
- type family AddChildTo test child trees :: [Tree k]
- type family AddEdge' edge trees hasFromRoot hasToRoot :: [Tree Symbol]
- type family AddEdge edge trees :: [Tree Symbol]
- type family SpanningTrees' edges acc :: [Tree Symbol]
- type family SpanningTrees edges :: [Tree Symbol]
- getSpanningTrees :: EdgeSchema es x unique -> Proxy (SpanningTrees es)
Documentation
We use promoted symbol values for the from
and to
type parameters. This
is the user-level data type when declaring the list of edges.
type family Deducible x :: Constraint Source
Some people just want to watch the world burn. Ideally, this shouldn't exist; poor error messages, and is very square peg - round hole.
type family Excluding x xs :: Constraint Source
not . elem
for lists of types, resulting in a constraint.
type family x =/= y :: Constraint Source
Trivial inequality for non-reflexivity of edges
class Acceptable a oldLoops unique Source
Simply reject anything that's been reached in the other direction. We expect an explicit type signature when uniqueness is needed, otherwise we will wait until invocation to see if the edges are unique.
(Excluding Symbol from (Lookup [Symbol] Symbol to excludeMap), Excluding Symbol to (Lookup [Symbol] Symbol from excludeMap), (=/=) Symbol Symbol from to) => Acceptable (EdgeType Symbol Symbol from to) excludeMap True | |
(Excluding Symbol from (Lookup [Symbol] Symbol to excludeMap), (=/=) Symbol Symbol from to) => Acceptable (EdgeType Symbol Symbol from to) excludeMap False |
type family PrependIfElem test a xs :: [k] Source
Add an explicit element to the head of a list, if the test is inside that list.
PrependIfElem t a (t : xs) = a : (t : xs) | |
PrependIfElem t a (u : xs) = u : PrependIfElem t a xs | |
PrependIfElem t a [] = [] |
type family DisallowIn new oldLoops keyFound :: [(Symbol, [Symbol])] Source
Update the exclusion map with the new edge: the from
key gets to
added,
likewise with keys that have from
in it's value list. We need to track if
the key exists yet.
DisallowIn (EdgeType from to) (`(from, xs)` : es) False = `(from, to : xs)` : DisallowIn (EdgeType from to) es True | |
DisallowIn (EdgeType from to) (`(key, vs)` : es) keyFound = `(key, PrependIfElem from to vs)` : DisallowIn (EdgeType from to) es keyFound | |
DisallowIn a [] True = [] | |
DisallowIn (EdgeType from to) [] False = `(from, to : [])` : [] |
data EdgeSchema edges nearLoops unique where Source
edges
is a list of types with kind EdgeKind
, while nearLoops
is a
map of the nodes transitively reachable by each node.
ENil :: EdgeSchema [] [] unique | |
ECons :: (Acceptable b oldLoops unique, EdgeValue from to ~ a, EdgeType from to ~ b, DisallowIn b oldLoops False ~ c) => !a -> EdgeSchema old oldLoops unique -> EdgeSchema (b : old) c unique |
unique :: EdgeSchema [] [] True Source
Utility for constructing an EdgeSchema
granularly
notUnique :: EdgeSchema [] [] False Source
type family AppendIfNotElemTrees c trees :: [Tree k] Source
Adds an empty c
tree to the list of trees uniquely
AppendIfNotElemTrees c (Node c xs : xss) = Node c xs : xss | |
AppendIfNotElemTrees c (Node x xs : xss) = Node x xs : AppendIfNotElemTrees c xss | |
AppendIfNotElemTrees c [] = Node c [] : [] |
type family AddChildTo test child trees :: [Tree k] Source
Adds c
as a child of any tree with a root t
. Assumes unique roots.
AddChildTo t c (Node t xs : xss) = Node t (AppendIfNotElemTrees c xs) : AddChildTo t c xss | |
AddChildTo t c (Node x xs : xss) = Node x (AddChildTo t c xs) : AddChildTo t c xss | |
AddChildTo t c [] = [] |
type family AddEdge' edge trees hasFromRoot hasToRoot :: [Tree Symbol] Source
We need to track if from
has is a root node or not. TODO: Some code repeat.
AddEdge' (EdgeType from to) [] False False = Node from (Node to [] : []) : (Node to [] : []) | |
AddEdge' (EdgeType from to) [] True False = Node to [] : [] | |
AddEdge' (EdgeType from to) [] False True = Node from (Node to [] : []) : [] | |
AddEdge' x [] True True = [] | |
AddEdge' (EdgeType from to) (Node from xs : xss) hasFromRoot hasToRoot = Node from (AppendIfNotElemTrees to xs) : AddEdge' (EdgeType from to) xss True hasToRoot | |
AddEdge' (EdgeType from to) (Node to xs : xss) hasFromRoot hasToRoot = Node to (AddEdge' (EdgeType from to) xs True True) : AddEdge' (EdgeType from to) xss hasFromRoot True | |
AddEdge' (EdgeType from to) (Node x xs : xss) hasFromRoot hasToRoot = Node x (AddEdge' (EdgeType from to) xs True True) : AddEdge' (EdgeType from to) xss hasFromRoot hasToRoot |
type family AddEdge edge trees :: [Tree Symbol] Source
Add to
as a child to every from
node in the accumulator.
type family SpanningTrees' edges acc :: [Tree Symbol] Source
Auxilliary function normally defined in a where
clause for manual folding.
SpanningTrees' [] trees = trees | |
SpanningTrees' (EdgeType from to : es) trees = SpanningTrees' es (AddEdge (EdgeType from to) trees) |
type family SpanningTrees edges :: [Tree Symbol] Source
Expects edges to already be type-safe
SpanningTrees edges = SpanningTrees' edges [] |
getSpanningTrees :: EdgeSchema es x unique -> Proxy (SpanningTrees es) Source