ecta-1.0.0.3
Safe HaskellNone
LanguageHaskell2010

Data.ECTA.Internal.ECTA.Type

Synopsis

Documentation

data RecNodeId Source #

Constructors

RecInt !Id

Reference to the Id of an interned Mu node

RecUnint Int

Reference to an as-yet uninterned Mu node, for which the Id is not yet known

The Int argument is used to distinguish between multiple nested Mu nodes.

NOTE: This is intentionally not an Id: it does not refer to the Id of any interned node.

RecDepth

Placeholder variable that we use only for depth calculations

The invariant that this is used only for depth calculations, along with the observation that depth calculation does not depend on the exact choice of variable, justifies subtituting any other variable for RecDepth in terms containing RecDepth in all contexts.

RecIntersect IntersectId

Refer to Mu-node-to-be-constructed during intersection

TODO: It is obviously not very elegant to have a constructor here specifically for one algorithm. Ideally, we would parameterize Node with the type of the identifiers in it. This might be useful also to rule out many other cases (specifically, most of the time we are dealing with fully interned nodes, and so the only constructor we expect is RecInt).

Instances

Instances details
Eq RecNodeId Source # 
Instance details

Defined in Data.ECTA.Internal.ECTA.Type

Ord RecNodeId Source # 
Instance details

Defined in Data.ECTA.Internal.ECTA.Type

Show RecNodeId Source # 
Instance details

Defined in Data.ECTA.Internal.ECTA.Type

Generic RecNodeId Source # 
Instance details

Defined in Data.ECTA.Internal.ECTA.Type

Associated Types

type Rep RecNodeId :: Type -> Type #

Hashable RecNodeId Source # 
Instance details

Defined in Data.ECTA.Internal.ECTA.Type

type Rep RecNodeId Source # 
Instance details

Defined in Data.ECTA.Internal.ECTA.Type

type Rep RecNodeId = D1 ('MetaData "RecNodeId" "Data.ECTA.Internal.ECTA.Type" "ecta-1.0.0.3-GsgcdoZGkFZA4oJqDsbHRS" 'False) ((C1 ('MetaCons "RecInt" 'PrefixI 'False) (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 Id)) :+: C1 ('MetaCons "RecUnint" 'PrefixI 'False) (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 Int))) :+: (C1 ('MetaCons "RecDepth" 'PrefixI 'False) (U1 :: Type -> Type) :+: C1 ('MetaCons "RecIntersect" 'PrefixI 'False) (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 IntersectId))))

data Edge Source #

Constructors

InternedEdge 

Bundled Patterns

pattern Edge :: Symbol -> [Node] -> Edge 

Instances

Instances details
Eq Edge Source # 
Instance details

Defined in Data.ECTA.Internal.ECTA.Type

Methods

(==) :: Edge -> Edge -> Bool #

(/=) :: Edge -> Edge -> Bool #

Ord Edge Source # 
Instance details

Defined in Data.ECTA.Internal.ECTA.Type

Methods

compare :: Edge -> Edge -> Ordering #

(<) :: Edge -> Edge -> Bool #

(<=) :: Edge -> Edge -> Bool #

(>) :: Edge -> Edge -> Bool #

(>=) :: Edge -> Edge -> Bool #

max :: Edge -> Edge -> Edge #

min :: Edge -> Edge -> Edge #

Show Edge Source # 
Instance details

Defined in Data.ECTA.Internal.ECTA.Type

Methods

showsPrec :: Int -> Edge -> ShowS #

show :: Edge -> String #

showList :: [Edge] -> ShowS #

Hashable Edge Source # 
Instance details

Defined in Data.ECTA.Internal.ECTA.Type

Methods

hashWithSalt :: Int -> Edge -> Int #

hash :: Edge -> Int #

Interned Edge Source # 
Instance details

Defined in Data.ECTA.Internal.ECTA.Type

Associated Types

data Description Edge Source #

type Uninterned Edge Source #

Eq (Description Edge) Source # 
Instance details

Defined in Data.ECTA.Internal.ECTA.Type

Generic (Description Edge) Source # 
Instance details

Defined in Data.ECTA.Internal.ECTA.Type

Associated Types

type Rep (Description Edge) :: Type -> Type #

Hashable (Description Edge) Source # 
Instance details

Defined in Data.ECTA.Internal.ECTA.Type

data Description Edge Source # 
Instance details

Defined in Data.ECTA.Internal.ECTA.Type

type Uninterned Edge Source # 
Instance details

Defined in Data.ECTA.Internal.ECTA.Type

type Rep (Description Edge) Source # 
Instance details

Defined in Data.ECTA.Internal.ECTA.Type

type Rep (Description Edge) = D1 ('MetaData "Description" "Data.ECTA.Internal.ECTA.Type" "ecta-1.0.0.3-GsgcdoZGkFZA4oJqDsbHRS" 'False) (C1 ('MetaCons "DEdge" 'PrefixI 'False) (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'SourceUnpack 'SourceStrict 'DecidedStrict) (Rec0 UninternedEdge)))

data UninternedEdge Source #

Instances

Instances details
Eq UninternedEdge Source # 
Instance details

Defined in Data.ECTA.Internal.ECTA.Type

Show UninternedEdge Source # 
Instance details

Defined in Data.ECTA.Internal.ECTA.Type

Generic UninternedEdge Source # 
Instance details

Defined in Data.ECTA.Internal.ECTA.Type

Associated Types

type Rep UninternedEdge :: Type -> Type #

Hashable UninternedEdge Source # 
Instance details

Defined in Data.ECTA.Internal.ECTA.Type

type Rep UninternedEdge Source # 
Instance details

Defined in Data.ECTA.Internal.ECTA.Type

type Rep UninternedEdge = D1 ('MetaData "UninternedEdge" "Data.ECTA.Internal.ECTA.Type" "ecta-1.0.0.3-GsgcdoZGkFZA4oJqDsbHRS" 'False) (C1 ('MetaCons "UninternedEdge" 'PrefixI 'True) (S1 ('MetaSel ('Just "uEdgeSymbol") 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 Symbol) :*: (S1 ('MetaSel ('Just "uEdgeChildren") 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 [Node]) :*: S1 ('MetaSel ('Just "uEdgeEcs") 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 EqConstraints))))

data Node Source #

Bundled Patterns

pattern Node :: [Edge] -> Node 
pattern Mu :: (Node -> Node) -> Node

Pattern only a Mu constructor

When we go underneath a Mu constructor, we need to bind the corresponding Rec node to something: that's why pattern matching on Mu yields a function. Code that wants to traverse the term as-is should match on the interned constructors instead (and then deal with the dangling references).

An identity function

foo (Mu f) = Mu f

will run in O(1) time:

foo (Mu f) = Mu f
  -- { expand view patern }
foo node | Just f <- matchMu node = createMu f
  -- { case for @InternedMu mu@ }
foo (InternedMu mu) | Just f <- matchMu (InternedMu m) = createMu f
  -- { definition of matchMu }
foo (InternedMu mu) = let f = \n' ->
                         if | n' == Rec (RecUnint (numNestedMu (internedMuBody mu))) ->
                               internedMuShape mu
                           | n' == Rec RecDepth ->
                               internedMuShape mu
                           | otherwise ->
                               substFree (internedMuId mu) n' (internedMuBody mu)
                      in createMu f
  -- { definition of createMu }
foo (InternedMu mu) = intern $ UninternedMu (f . Rec)

At this point, intern will call `shape (f . Rec)`, which will call `f . Rec` twice: once with RecDepth to compute the depth, and then once again with that depth to substitute a placeholder. Both of these special cases will use internedMuShape (and moreover, the depth calculation on internedMuShape is O(1)).

Instances

Instances details
Eq Node Source # 
Instance details

Defined in Data.ECTA.Internal.ECTA.Type

Methods

(==) :: Node -> Node -> Bool #

(/=) :: Node -> Node -> Bool #

Ord Node Source # 
Instance details

Defined in Data.ECTA.Internal.ECTA.Type

Methods

compare :: Node -> Node -> Ordering #

(<) :: Node -> Node -> Bool #

(<=) :: Node -> Node -> Bool #

(>) :: Node -> Node -> Bool #

(>=) :: Node -> Node -> Bool #

max :: Node -> Node -> Node #

min :: Node -> Node -> Node #

Show Node Source # 
Instance details

Defined in Data.ECTA.Internal.ECTA.Type

Methods

showsPrec :: Int -> Node -> ShowS #

show :: Node -> String #

showList :: [Node] -> ShowS #

Hashable Node Source # 
Instance details

Defined in Data.ECTA.Internal.ECTA.Type

Methods

hashWithSalt :: Int -> Node -> Int #

hash :: Node -> Int #

Interned Node Source # 
Instance details

Defined in Data.ECTA.Internal.ECTA.Type

Associated Types

data Description Node Source #

type Uninterned Node Source #

Pathable Node Node Source # 
Instance details

Defined in Data.ECTA.Internal.ECTA.Operations

Associated Types

type Emptyable Node Source #

Eq (Description Node) Source # 
Instance details

Defined in Data.ECTA.Internal.ECTA.Type

Generic (Description Node) Source # 
Instance details

Defined in Data.ECTA.Internal.ECTA.Type

Associated Types

type Rep (Description Node) :: Type -> Type #

Hashable (Description Node) Source # 
Instance details

Defined in Data.ECTA.Internal.ECTA.Type

Pathable [Node] Node Source # 
Instance details

Defined in Data.ECTA.Internal.ECTA.Operations

Associated Types

type Emptyable Node Source #

Methods

getPath :: Path -> [Node] -> Emptyable Node Source #

getAllAtPath :: Path -> [Node] -> [Node] Source #

modifyAtPath :: (Node -> Node) -> Path -> [Node] -> [Node] Source #

data Description Node Source # 
Instance details

Defined in Data.ECTA.Internal.ECTA.Type

type Uninterned Node Source # 
Instance details

Defined in Data.ECTA.Internal.ECTA.Type

type Emptyable Node Source # 
Instance details

Defined in Data.ECTA.Internal.ECTA.Operations

type Emptyable Node Source # 
Instance details

Defined in Data.ECTA.Internal.ECTA.Operations

type Rep (Description Node) Source # 
Instance details

Defined in Data.ECTA.Internal.ECTA.Type

type Rep (Description Node) = D1 ('MetaData "Description" "Data.ECTA.Internal.ECTA.Type" "ecta-1.0.0.3-GsgcdoZGkFZA4oJqDsbHRS" 'False) (C1 ('MetaCons "DNode" 'PrefixI 'False) (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 UninternedNode)))

data InternedNode Source #

Constructors

MkInternedNode 

Fields

Instances

Instances details
Show InternedNode Source # 
Instance details

Defined in Data.ECTA.Internal.ECTA.Type

data InternedMu Source #

Constructors

MkInternedMu 

Fields

  • internedMuId :: !Id

    Id of the node itself

  • internedMuBody :: !Node

    The body of the Mu

    Recursive occurrences to this node should be

    Rec (RecNodeId internedMuId)
  • internedMuShape :: !Node

    The body of the Mu, before it was assigned an Id

    Invariant:

       substFree internedMuId (Rec (RecUnint (numNestedMu internedMuBody)) internedMuBody
    == internedMuShape

Instances

Instances details
Show InternedMu Source # 
Instance details

Defined in Data.ECTA.Internal.ECTA.Type

data UninternedNode Source #

Constructors

UninternedNode ![Edge] 
UninternedEmptyNode 
UninternedMu !(RecNodeId -> Node)

Recursive node

The function should be parametric in the Id:

substFree i (Rec j) (f i) == f j

See shape for additional discussion.

data IntersectId Source #

Context-free references to a Mu node introduced by intersect

Background: This is a generalization of the idea to be able to refer to the "immediately enclosing binder", and then only deal with graphs with the property that we never need to refer past that enclosing binder. This too would allow us to refer to a Mu node without knowing its Id, at the cost of requiring a substitution when we discover that Id to return this into a RecInt. The generalization is that all we need to some way to refer to that Mu node concretely, without Id, but we can: intersection introduces Mu whenever it encounters a Mu on the left or the right, /and will then not introduce another Mu for that same intersection problem (at least, not in the same scope). This means that the Id of the left and right operand will indeed uniquely identify the Mu node to be constructed by intersect.

Furthermore, since we cache the free variables in a term, we have a cheap check to see if we need the Mu node at all. This means that if the input graphs satisfy the property that there are references past Mu nodes, the output should too: we will not introduce redundant Mu nodes.

NOTE: Although intersect has three cases in which it introduces Mu nodes (Mu in both operands, Mu in the left, or Mu in the right), we don't need that distinction here: we just need to know the Id of the two operands, so that if we see a call to intersect again with those same two operands (no matter what kind of nodes they are), we can refer to the newly constructed Mu node.

Instances

Instances details
Eq IntersectId Source # 
Instance details

Defined in Data.ECTA.Internal.ECTA.Type

Ord IntersectId Source # 
Instance details

Defined in Data.ECTA.Internal.ECTA.Type

Show IntersectId Source # 
Instance details

Defined in Data.ECTA.Internal.ECTA.Type

Generic IntersectId Source # 
Instance details

Defined in Data.ECTA.Internal.ECTA.Type

Associated Types

type Rep IntersectId :: Type -> Type #

Hashable IntersectId Source # 
Instance details

Defined in Data.ECTA.Internal.ECTA.Type

type Rep IntersectId Source # 
Instance details

Defined in Data.ECTA.Internal.ECTA.Type

type Rep IntersectId = D1 ('MetaData "IntersectId" "Data.ECTA.Internal.ECTA.Type" "ecta-1.0.0.3-GsgcdoZGkFZA4oJqDsbHRS" 'False) (C1 ('MetaCons "UnsafeIntersectId" 'PrefixI 'False) (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 Id) :*: S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 Id)))

pattern IntersectId :: Id -> Id -> IntersectId Source #

numNestedMu :: Node -> Int Source #

Maximum number of nested Mus in the term

@O(1) provided that there are no unbounded Mu chains in the term.

substFree :: RecNodeId -> Node -> Node -> Node Source #

Substitution

substFree i n will replace all occurrences of Rec (RecNodeId i) by n. We appeal to the uniqueness of node IDs and assume that all occurrences of i must be free (in other words, that any occurrences of Mu will have a different identifier.

Postcondition:

substFree i (Rec (RecNodeId i)) == id

freeVars :: Node -> Set RecNodeId Source #

Free variables in the term

O(1) in the size of the graph, provided that there are no unbounded Mu chains in the term. O(log n)@ in the number of free variables in the graph, which we expect to be orders of magnitude smaller than the size of the graph (indeed, we don't expect more than a handful).

modifyNode :: Node -> ([Edge] -> [Edge]) -> Node Source #

An optimized Node constructor that avoids the interning/preprocessing of the Node constructor when nothing changes

createMu :: (Node -> Node) -> Node Source #

Construct recursive node

Implementation note: createMu and matchMu interact in non-trivial ways; see docs of the Mu pattern synonym for performance considerations.