Prefix Notation conversion into a tree is usually done like this:
Create a binary tree from an algebraic expression
However, I need to support so called chainable operations that have more than two operands. If that operation is splittable i.e
(+ a b c) = (+(+ a b) c)
there is no problem.
+
/ \
+ c
/ \
a b
However if an operator is not splittable this does not work. One example is the pairwise distinct operator.
(distinct a b c) != (distinct (distinct a b) c)
the left side implies a != b, a != c and b != c, while the right side implies only a != b and b != c. Trying to build an n-ary tree would probably lead to not being able to traverse the tree very well:
distinct
/ | \
a b c
Does somebody have experience with this kind of problem and has an idea on how to solve the issue?
The c# System.Linq.Expressions namespace solves it by having a big range of node types, and a base class visitor, where you can override the visit method of each node type, by default just traversing the whole tree. For example there is a node type for calling a method, where the method definition, the object, and all arguments are all children of the MethodCallExpression node, and the return value is what the node represents. You can see it is not a binary tree, not even anything regular.
Related
I've seen various versions of the Lens Laws. Not sure if they're all intended to be equivalent, so for definiteness I'll use the version on StackOverflow against tag Lenses [Edward Kmett ~ 5 years ago]
(I'm asking because I want more of a handle on bi-directional programming.)
Using a as a structure, b as a component/value in the structure:
get (set b a) = b
Ok. What you get is what you've put. Seems essential for anything calling itself a data structure/container. I might have a slight q: where did the initial a come from? Could I go directly get a? What would that mean?
get (set b' (set b a)) = b'
?I believe this is intended to be telling me: what you get is what you last put (and anything you put before is lost forever). But it doesn't actually say that. It doesn't (for example) exclude that the lens is a stack-within-a -- i.e. get behaves like pop. So if I do a second get it might return the earlier b. IOW it needs to say: once you've set b' (whatever-a), get will always return b' ad infinitum.
This is law is sometimes written in the form: set b' (set b a) = set b' a. But I don't like that at all, which brings me to:
set (get a) a = a
Putting what you've already got does nothing. (That seems a barely interesting thing to say: doesn't it follow from Law 1?) But an equality test on the structure is breaking the abstraction. We (as clients of the structure) don't care how the structure organises itself internally. Our interface is in terms of the methods get, set. Putting what you've already got might change the structure's value for all we care -- just as long as a get returns that value we put.
If there's something crucial about the value/contents of set (get a) a, can't that be expressed in terms of get/set? And if it can't, why do we care?
All these laws are in terms of a single lens. So they would hold if the structure was merely a single 'slot' -- which seems a lot of machinery for something aka a 'variable'.
What does seem to be missing is anything about how you can combine distinct lenses to work through a more complex structure. Such that the structure allows each lens to work orthogonally. I believe there's a van Laarhoven law:
-- I need two lenses, so I'll use get', set' as well as get, set
get' (set b (set' b' a)) = b'
Do I not need a law like that? Please explain.
I haven't used this formalism before, so it might show in my answer.
This is a mathematical law. It doesn't matter where a comes from, as long as it satisfies the relevant mathematical requirements. In programming, you could define it in your code, load it from a file, parse it from network call, build it recursively; whatever.
It can't say that. get doesn't return a new structure, only the value; and the whole point of lenses is to create a framework for immutable, side-effect-free structures. Let a' be (set b' (set b a)); get a' will return b' each and every time, because a' can't change, and get is pure function; there is no place for state to be stored. Your "get will always return b' ad infinitum" is assumed to always be true in for a pure function, there is no need for a further stipulation. To implement a stack, you need one of two things: either for it to be mutable, side-effectful (so that get a == get a is not necessarily true), or the manipulation functions need to return the new stack - both put and get.
I failed to construct a counterexample for this, probably because it is intuitively so strong. Here is a very tenuous counterexample: Let get a (Container b _) = b, set b (Container b c) = Container b (c + 1), set b (Container b' _) = Container b 0. Furthermore, let a = Container b' 0 and b != b'. First law: get (set b a) = get (Container b 0) = b - OK. Second law: get (set b' (set b a)) = get (set b' (Container b 0)) = get (Container b' 0) = b' - OK. However, set (get a) a = set (get (Container b' 0)) (Container b' 0) = set b' (Container b') = Container b' 1 != a - not OK. Thus, it does not follow from the first law. Without this, you cannot test two structures for equality, and would instead need to iterate each accessor to prove that the two structures are equal (and as a JavaScript programmer, let me tell you: not having object identity function is really awkward).
You do. Imagine this: set b a = Container b, get (Container b) = b. First law: get (set b a) = get (Container b) = b - OK. Second law: get (set b' (set b a)) = get (set b' (Container b)) = get (Container b') = b' - OK; Third law: let a == Container b: set (get a) a = set (get (Container b)) a = set b a = Container b = a - OK. All three laws are satisfied with this very simple (and kind of obviously wrong) definition. Now let's add set' b a = Container' b, get' (Container' b) = b), and see what happens: get' (set b (set' b' a)) = get' (set b (Container' b')) = get' (Container b)... and this can't get evaluated. Oopsie. Or, imagine this: set b a = Container b 0, get (Container b _) = b, set' b a = Container b 1, get' (Container b _) = b. In this case, get' (set b (set' b' a)) = get' (set b (Container b' 1)) = get' (Container b 0) = b - not OK. This law guarantees that the values set by set' will be preserved in the structure even if we apply set (something that is definitely not the case in this example).
If you're coming at this with expectations of Bidirectional Programming, I'm not surprised you're puzzled, AntC.
The FAQ page Resources [1] cites Pierce and Voigtländer (both of whom state similar laws); but really they're working with a quite different semantics. For example the Pierce et al 2005 paper:
The get component of a lens corresponds exactly to a view definition. In order to support a compositional approach, we take the perspective that a view state is an entire database (rather than just a single relation, as in many treatments of views).
So these are 'views' in the database sense (and that leads to the punning on terms from optics). There's always a 'base' schema definition (data structure) to/from which the lenses transform the view. Both Pierce and Voigtländer are trying to manage the 'size and shape' of data structures, to preserve transformations between them. Then no wonder they're thinking that the 'base' is the chief holder of content, and the lenses merely mechanisms to look through.
With functional references, there's no such difficulty. Lenses focus on 'slots' in a single data structure. And the structure is treated as abstract.
If the functional references approach wants to lay down laws in terms of 'slots', and specifically treat what Pierce calls oblivious lenses, it has to take on the semantics for the parts of the structure outside the lens. What the Voigtländer et al 2012 paper deals with using the res (residue) function; or prior work on database views [Bancilhon & Spyratos 1981] calls the "complement".
The set function in the laws quoted in the O.P. is oblivious in the sense it ignores the current content of the 'slot' and overwrites it. Lenses aren't necessarily like that. Recent treatments use an upd function (with an additional parameter f for the update to apply to the current value). Note
get (upd f a) = f (get a).
get (set b a) = b = get (upd (const b) a). (Law 1)
Except that not all lens upd operations observe those equivalences. There is, for example, the neat trick of a lens that gets the day slot from a date; but whose upd (+ 1) increments the whole date. getDay (updDay (+ 1) (Date {year = 2017, month = 2, day = 28}) ) returns 1, not 29.
To the specific questions in the O.P.
"slight q": the initial a comes from a create function [Voigtländer]
and there's a bunch of create/get laws.
Or is already in the 'base' schema [Pierce].
#Amadan's answer is right on the money. get and set are pure functions.
get must return whatever was last set, by Law 1. So Law 2 seems pointless.
Is important to state for Pierce and Voigtländer because they regard the 'base' as critical.
For functional references (if the data structure is supposed to be held abstract),
stating this law is breaking the abstraction.
It is also failing to state the behaviour for other Lenses into the structure,
if set changes the value -- which is surely what Lens user wants to understand.
So again seems pointless.
Note neither Pierce's nor Voigtländer's approaches expect more than one Lens.
If two Lenses focus on independent slots within a structure, both of these hold:
-- continuing to use get'/set' as well as get/set
∀ b b' . get' (set b (set' b' a)) = b' -- law for set' inside set
∀ b' b . get (set' b' (set b a)) = b -- law for set inside set'
If two Lenses interfere/overlap, neither equation holds (in general for all values in the domain of set, set').
So to take the 'worst' but still plausible case from above of getDay/updDayfocussing inside getDate/setDate:
Law 1 holds for getDate/setDate; but updDay doesn't behave like a version of set.
Laws 2 & 3 hold (but seem pointless).
There's no laws we can usefully write about their interaction.
I guess the best we could do is segregate the Lenses that focus inside the same structure
into groupings that do/don't mutually interfere.
Overall I don't think the Lens Laws are much help in understanding Lenses as they are used nowadays.
[1] https://github.com/ekmett/lens/wiki/FAQ#lens-resources
Assuming here is a binary search tree, and given the rule that above(X,Y) - X is directly above Y. Also I created the rule root(X) - X has no parent.
Then, I was trying to figure out what the depth of node in this tree.
Assume the root node of tree is "r" So I got fact level(r,0). In order to implement the rule level(N,D) :-, what I was thinking is it should be have a recursion here.
Thus, I tried
level(N,D): \+ root(N), above(X,N), D is D+1, level(X,D).
So if N is not a root, there has a node X above N and level D plus one, then recursion. But when I tested this, it just works for the root condition. When I created more facts, such as node "s" is leftchild of node "r", My query is level(s,D). It returns me "no". I traced the query, it shows me
1 1 Call: level(s,_16) ?
1 1 Fail: level(s,_16) ?
I just confusing why it fails when I call level(s,D)?
There are some problems with your query:
In Prolog you cannot write something like D is D+1, because a variable can only be assigned one value;
at the moment you call D is D+1, D is not yet instantiated, so it will probably cause an error; and
You never state (at least not in the visible code) that the level/2 of the root is 0.
A solution is to first state that the level of any root is 0:
level(N,0) :-
root(N).
Now we have to define the inductive case: first we indeed look for a parent using the above/2 predicate. Performing a check that N is no root/1 is not necessary strictly speaking, because it would conflict with the fact that there is an above/2. Next we determine the level of that parent LP and finally we calculate the level of our node by stating that L is LP+1 where L is the level of N and LP the level op P:
level(N,L) :-
above(P,N),
level(P,LP),
L is LP+1.
Or putting it all together:
level(N,0) :-
root(N).
level(N,L) :-
above(P,N),
level(P,LP),
L is LP+1.
Since you did not provide a sample tree, I have no means to test whether this predicate behaves as you expect it to.
About root/1
Note that by writing root/1, you introduce data duplication: you can simply write:
root(R) :-
\+ above(_,R).
My Neo4j database contains relationships that may have a special property:
(a) -[{sustains:true}]-> (b)
This means that a sustains b: when the last node that sustains b is deleted, b itself should be deleted. I'm trying to write a Cypher statement that deletes a given node PLUS all nodes that now become unsustained as a result. This may set off a chain reaction, and I don't know how to encode this in Cypher. Is Cypher expressive enough?
In any other language, I could come up with a number of ways to implement this. A recursive algorithm for this would be something like:
delete(a) :=
MATCH (a) -[{sustains:true}]-> (b)
REMOVE a
WITH b
MATCH (aa) -[{sustains:true}]-> (b)
WHERE count(aa) = 0
delete(b)
Another way to describe the additional set of nodes to delete would be with a fixed point function:
setOfNodesToDelete(Set) :=
RETURN Set' ⊆ Set such that for all n ∈ Set'
there is no (m) -[{sustains:true}]-> (n) with m ∉ Set
We would start with the set of all z such that (a) -[{sustains:true}*1..]-> (z), then delete a, run setOfNodesToDelete on the set until it doesn't change anymore, then delete the nodes specified by the set. This requires an unspecified number of iterations.
Any way to accomplish my goal in Cypher?
I'm having trouble understanding the letrec definition for HM system that is given on Wikipedia, here: https://en.wikipedia.org/wiki/Hindley%E2%80%93Milner_type_system#Recursive_definitions
For me, the rule translates roughly to the following algorithm:
infer types on everything in the letrec definition part
assign temporary type variables to each defined identifier
recursively process all definitions with temporary types
in pairs, unify the results with the original temporary variables
close (with forall) the inferred types, add them to the basis (context) and infer types of the expression part with it
I'm having trouble with a program like this:
letrec
p = (+) --has type Uint -> Uint -> Uint
x = (letrec
test = p 5 5
in test)
in x
The behavior I'm observing is as follows:
definition of p gets temporary type a
definition of x gets some temporary type too, but that's out of our scope now
in x, definition of test gets a temporary type t
p gets the temporary type a from the scope, using the HM rule for a variable
(f 5) gets processed by HM rule for application, resulting type is b (and the unification that (a unifies with Uint -> b)
((p 5) 5) gets processed by the same rule, resulting in more unifications and type c, a now in result unifies with Uint -> Uint -> c
now, test gets closed to type forall c.c
variable test of in test gets the type instance (or forall c.c) with fresh variables, accrodingly to the HM rule for variable, resulting in test :: d (that is unified with test::t right on)
resulting x has effectively type d (or t, depending on the mood of unification)
The problem: x should obviously have type Uint, but I see no way those two could ever unify to produce the type. There is a loss of information when the type of test gets closed and instance'd again that I'm not sure how to overcome or connect with substitutions/unifications.
Any idea how the algorithm should be corrected to produce x::Uint typing correctly? Or is this a property of HM system and it simply will not type such case (which I doubt)?
Note that this would be perfectly OK with standard let, but I didn't want to obfuscate the example with recursive definitions that can't be handled by let.
Thanks in advance
Answering my own question:
The definition on the Wiki is wrong, although it works to certain extent at least for type checking.
Most simple and correct way to add recursion to HM system is to use fix predicate, with definition fix f = f (fix f) and type forall a. (a->a) -> a. Mutual recursion is handled by double fixpoint, etc.
Haskell approach to the problem (described at https://gist.github.com/chrisdone/0075a16b32bfd4f62b7b#binding-groups ) is (roughly) to derive an incomplete type for all functions and then run the derivation again to check them against each other.
Concept
I am implementing an interpreter that allows a user to define arbitrary combinators and apply them to arbitrary terms. For example, a user may define the Church encoding for pairs by inputting the following combinator definitions:
pair a b c → c a b
true a b → a
first a → a true
The user may then input first (pair a b), which is reduced step-by-step according to the previously defined rules:
first (pair a b)
→ pair a b true
→ true a b
→ a
Other combinators may also be defined, such as those used in the SKI combinator calculus:
S x y z → x z (y z)
K x y → x
I x → x
The identity combinator could also be defined in terms of the first two combinators by I → S S K K or I → S K (K K) or I = S K x. The universal iota combinator could then be defined by:
ι x → x S K
These examples hopefully illustrate what I am trying to do.
Implementation
I am attempting to implement this using graph reduction and a graph rewriting system. Let tree be a data type defined recursively by
tree = leaf | (tree tree)
This is a binary tree, where nodes may be either leafs (terminal nodes) or branches (internal nodes) consisting of a pair of subtrees. The branches represent the application of a term to another term, while leaves represent combinators and arguments. Let rule be a data type defined by
rule = (tree tree)
This corresponds to a reduction rule that transforms the left tree into the right tree (a → b). The list of rules may then be defined by
rules = rule | (rule rules)
Effectively, when evaluating an expression such as pair a b c → c a b, the interpreter constructs a tree of the form (((pair a) b) c) corresponding to the left hand side, a tree of the form ((c a) b) corresponding to the right hand side, constructs a pair of both trees corresponding to a rule (where a,b,c are somehow specified to be arbitrary parameters and not necessarily combinators or terminal symbols), and appends this pair to the list rules. When reducing an expression of the form first (pair a b), the interpreter constructs the corresponding tree (first ((pair a) b)) and applies the reduction rules as follows:
(first ((pair a) b))
→ (((pair a) b) true)
→ ((true a) b)
→ a
To do this, the interpreter must perform pattern matching on the tree and its subtrees, "moving around" the combinators and arbitrary parameters to construct a new tree corresponding to the right hand side of the rule. An example implementation of the tree structure in C is given by
struct tree_t {
bool is_leaf;
union {
char* symbol;
struct {
tree_t* left;
tree_t* right;
};
};
};
A pattern matching function could be implemented as
bool matches(tree_t* pattern, tree_t* replacement) {
if (pattern -> is_leaf && replacement -> is_leaf)
//do stuff, return a boolean
else if (pattern -> is_leaf && replacement -> is_branch)
//do stuff, return a boolean
else if (pattern -> is_branch && replacement -> is_leaf)
//do stuff, return a boolean
else if (pattern -> is_branch && replacement -> is_branch)
return matches(pattern -> left, replacement -> left) && matches(pattern -> right, replacement -> right);
//The above tests for equality recursively by testing for equality in each subtree.
}
However, I am unsure of how to implement important details of this process, including:
Matching an input tree with the LHS tree of a reduction rule.
Transforming the input tree into the RHS tree of the reduction rule, preserving parameters (which may be leaves or branches) and "moving them around" around to their appropriate places.
I believe pattern-matching on a node would involve examining the left child and right child of the node and so on, until terminal nodes are reached. Does anyone know of a program or tutorial online that has implemented a similar concept in C and that I could learn from? Am I even on the right track in approaching the problem through this method, or is there a simpler way?
You need to take it in two separate steps. A pattern matcher matches a pattern against a tree, and builds a dictionary mapping variables in the pattern to values in the tree.
Then you pass that dictionary to a separate function that fills in the replacement, by replacing variables with their values from the dictionary.
The pattern matching approach described in SICP will work just fine in C, though you may find it easier to use a mutable data structure for the dictionary. See https://mitpress.mit.edu/sicp/full-text/sicp/book/node99.html