Infinite union of regular language can be context free.
Is this statement true or false?
According to answer key, this is true! What I know is that infinite union or intersection is not closed under union/intersection.
Can anyone explain the procedure or logic behind this? How to know the infinite union / intersection for a particular language?
The statement is true, yes. It asks if such a union CAN be context-free, not if it always is. A verx simple example is taking the union of infinitely many times the same language; the result is just the original language, and if it was regular the result is, too. Or the union of all the { a^i } is the regular language a^*.
On the other hand, the infinite union can be uncomputable. Take a non-enumerable language L and the infinitely many (regular) singleton sets that contain exactly one word from this language. Their union is L and thus non-enumerable.
Related
Grouping operator ( ) in JavaScript
The grouping operator ( ) controls the precedence of evaluation in expressions.
Does the functionality ( ) in JavaScript itself differ from Haskell or any other programming languages?
In other words,
Is the functionality ( ) in programming languages itself affected by evaluation strategies ?
Perhaps we can share the code below:
a() * (b() + c())
to discuss the topic here, but not limited to the example.
Please feel free to use your own examples to illustrate. Thanks.
Grouping parentheses mean the same thing in Haskell as they do in high school mathematics. They group a sub-expression into a single term. This is also what they mean in Javascript and most other programming language1, so you don't have to relearn this for Haskell coming from other common languages, if you have learnt it the right way.
Unfortunately, this grouping is often explained as meaning "the expression inside the parentheses must be evaluated before the outside". This comes from the order of steps you would follow to evaluate the expression in a strict language (like high school mathematics). However the grouping really isn't really about the order in which you evaluate things, even in that setting. Instead it is used to determine what the expression actually is at all, which you need to know before you can do anythign at all with the expression, let alone evaluate it. Grouping is generally resolved as part of parsing the language, totally separate from the order in which any runtime evaluation takes place.
Let's consider the OP's example, but I'm going to declare that function call syntax is f{} rather than f() just to avoid using the same symbol for two purposes. So in my newly-made-up syntax, the OP's example is:
a{} * (b{} + c{})
This means:
a is called on zero arguments
b is called on zero arguments
c is called on zero arguments
+ is called on two arguments; the left argument is the result of b{}, and the right argument is the result of c{}
* is called on two arguments: the left argument is the result of a{}, and the right argument is the result of b{} + c{}
Note I have not numbered these. This is just an unordered list of sub-expressions that are present, not an order in which we must evaluate them.
If our example had not used grouping parentheses, it would be a{} * b{} + c{}, and our list of sub-expressions would instead be:
a is called on zero arguments
b is called on zero arguments
c is called on zero arguments
+ is called on two arguments; the left argument is the result of a{} * b{}, and the right argument is the result of c{}
* is called on two arguments: the left argument is the result of a{}, and the right argument is the result of b{}
This is simply a different set of sub-expressions from the first (because the overall expression doesn't mean the same thing). That is all that grouping parentheses do; they allow you to specify which sub-expressions are being passed as arguments to other sub-expressions2.
Now, in a strict language "what is being passed to what" does matter quite a bit to evaluation order. It is impossible in a strict language to call anything on "the result of a{} + b{} without first having evaluated a{} + b{} (and we can't call + without evaluating a{} and b{}). But even though the grouping determines what is being passed to what, and that partially determines evaluation order3, grouping isn't really "about" evaluation order. Evaluation order can change as a result of changing the grouping in our expression, but changing the grouping makes it a different expression, so almost anything can change as a result of changing grouping!
Non-strict languages like Haskell make it especially clear that grouping is not about order of evaluation, because in non-strict languages you can pass something like "the result of a{} + b{}" as an argument before you actually evaluate that result. So in my lists of subexpressions above, any order at all could potentially be possible. The grouping doesn't determine it at all.
A language needs other rules beyond just the grouping of sub-expressions to pin down evaluation order (if it wants to specify the order), whether it's strict or lazy. So since you need other rules to determine it anyway, it is best (in my opinion) to think of evaluation order as a totally separate concept than grouping. Mixing them up seems like a shortcut when you're learning high school mathematics, but it's just a handicap in more general settings.
1 In languages with roughly C-like syntax, parentheses are also used for calling functions, as in func(arg1, arg2, arg3). The OP themselves has assumed this syntax in their a() * (b() + c()) example, where this is presumably calling a, b, and c as functions (passing each of them zero arguments).
This usage is totally unrelated to grouping parentheses, and Haskell does not use parentheses for calling functions. But there can be some confusion because the necessity of using parentheses to call functions in C-like syntax sometimes avoids the need for grouping parentheses e.g. in func(2 + 3) * 6 it is unambiguous that 2 + 3 is being passed to func and the result is being multiplied by 6; in Haskell syntax you would need some grouping parentheses because func 2 + 3 * 6 without parentheses is interpreted as the same thing as (func 2) + (3 * 6), which is not func (2 + 3) * 6.
C-like syntax is not alone in using parentheses for two totally unrelated purposes; Haskell overloads parentheses too, just for different things in addition to grouping. Haskell also uses them as part of the syntax for writing tuples (e.g. (1, True, 'c')), and the unit type/value () which you may or may not want to regard as just an "empty tuple".
2 Which is also what associativity and precedence rules for operators do. Without knowing that * is higher precedence than +, a * b + c is ambiguous; there would be no way to know what it means. With the precedence rules, we know that a * b + c means "add c to the result of multiplying a and b", but we now have no way to write down what we mean when we want "multiply a by the result of adding b and c" unless we also allow grouping parentheses.
3 Even in a strict language the grouping only partially determines evaluation order. If you look at my "lists of sub-expressions" above it's clear that in a strict language we need to have evaluated a{}, b{}, and c{} early on, but nothing determines whether we evaluate a{} first and then b{} and then c{}, or c{} first, and then a{} and then b{}, or any other permutation. We could even evaluate only the two of them in the innermost +/* application (in either order), and then the operator application before evaluating the third named function call, etc etc.
Even in a strict language, the need to evaluate arguments before the call they are passed to does not fully determine evaluation order from the grouping. Grouping just provides some constraints.
4 In general in a lazy language evaluation of a given call happens a bit at a time, as it is needed, so in fact in general all of the sub-evaluations in a given expression could be interleaved in a complicated fashion (not happening precisely one after the other) anyway.
To clarify the dependency graph:
Answer by myself (the Questioner), however, I am willing to be examined, and still waiting for your answer (not opinion based):
Grouping operator () in every language share the common functionality to compose Dependency graph.
In mathematics, computer science and digital electronics, a dependency graph is a directed graph representing dependencies of several objects towards each other. It is possible to derive an evaluation order or the absence of an evaluation order that respects the given dependencies from the dependency graph.
dependency graph 1
dependency graph 2
the functionality of Grouping operator () itself is not affected by evaluation strategies of any languages.
For an assignment I have to write a pseudorandom number generator in Haskell. I'm not sure how it's possible in Haskell to "remember" the last value returned by the function, since that's required by the definition of a pseudorandom number generator (the next number in the sequence is based on the last number returned).
In an imperative language I could just keep a global variable or something:
int last_rand;
int myRandom()
{
last_rand = (some operation on last_rand);
return last_rand;
}
But in Haskell, or at least, from what I know of Haskell, there's no way to store and update a mutable record of values returned by a function... how can I go about this?
I would like to recommend you to read Chapter 9 Input and Output - Randomness and Chapter 13 For a Few Monads More - Making monads (lookup for Tasteful stageful computations section) of Learn You a Haskell book.
There you would find solution (or keys for solution) of your assignment.
P. S. I give links to book, because there is no sense in copy-pasting it's content. Just straight links :)
I have an interesting question, but I'm not sure exactly how to phrase it...
Consider the lambda calculus. For a given lambda expression, there are several possible reduction orders. But some of these don't terminate, while others do.
In the lambda calculus, it turns out that there is one particular reduction order which is guaranteed to always terminate with an irreducible solution if one actually exists. It's called Normal Order.
I've written a simple logic solver. But the trouble is, the order in which it processes the constraints seems to have a huge effect on whether it finds any solutions or not. Basically, I'm wondering whether something like a normal order exists for my logic programming language. (Or wether it's impossible for a mere machine to deterministically solve this problem.)
So that's what I'm after. Presumably the answer critically depends on exactly what the "simple logic solver" is. So I will attempt to briefly describe it.
My program is closely based on the system of combinators in chapter 9 of The Fun of Programming (Jeremy Gibbons & Oege de Moor). The language has the following structure:
The input to the solver is a single predicate. Predicates may involve variables. The output from the solver is zero or more solutions. A solution is a set of variable assignments which make the predicate become true.
Variables hold expressions. An expression is an integer, a variable name, or a tuple of subexpressions.
There is an equality predicate, which compares expressions (not predicates) for equality. It is satisfied if substituting every (bound) variable with its value makes the two expressions identical. (In particular, every variable equals itself, bound or not.) This predicate is solved using unification.
There are also operators for AND and OR, which work in the obvious way. There is no NOT operator.
There is an "exists" operator, which essentially creates local variables.
The facility to define named predicates enables recursive looping.
One of the "interesting things" about logic programming is that once you write a named predicate, it typically works fowards and backwards (and sometimes even sideways). Canonical example: A predicate to concatinate two lists can also be used to split a list into all possible pairs.
But sometimes running a predicate backwards results in an infinite search, unless you rearrange the order of the terms. (E.g., swap the LHS and RHS of an AND or an OR somehwere.) I'm wondering whether there's some automated way to detect the best order to run the predicates in, to ensure prompt termination in all cases where the solution set is exactually finite.
Any suggestions?
Relevant paper, I think: http://www.cs.technion.ac.il/~shaulm/papers/abstracts/Ledeniov-1998-DCS.html
Also take a look at this: http://en.wikipedia.org/wiki/Constraint_logic_programming#Bottom-up_evaluation
Which do the concepts control flow, data type, statement, expression and operation belong to? Syntax or semantics?
What is the relation between control flow, data type, statement, expression, operation, function, ...? How a program is built from these primitives level by level?
I would like to understand these primitive concepts and their relations in order to figure out what aspects of a new language should one learn.
Thanks and regards!
All of those language elements have both syntax (how it is written) and semantics (how the way it is written corresponds to what it actually means). Control flow determines which statements are executed and when, expressions yield a value and can be made up of functions and other language elements (although the details depend on the programming language). An operation is usually a sequence of statements. The meaning of "function" varies from language to language; in some languages, any operation that can be invoked by name is a function. In other languages, a function is an operation that yields a result (as opposed to a procedure that does not report a result). Some languages also require that functions be non-mutating while procedures can be mutating, although this varies from language to language. Data types encapsulate both data and the operations/procedures/functions that can be operated on that data.
They belong to both worlds:
Syntax will describe which are the operators, which are primitive types (int, float), which are the keywords (return, for, while). So syntax decides which "words" you can use in the programming language. With word I mean every single possible token: = is a token, void is a token, varName12345 is a token that is considered as an identifier, 12.4 is a token considered as a float and so on..
Semantics will describe how these tokens can be combined together inside you language.
For example you will have that while semantics is something like:
WHILE ::= 'while' '(' CONDITION ')' '{' STATEMENTS '}'
CONDITION ::= CONDITION '&&' CONDITION | CONDITION '||' CONDITION | ...
STATEMENTS ::= STATEMENT ';' STATEMENTS | empty_rule
and so on. This is the grammar of the language that describes exactly how the language is structured. So it will be able to decide if a program is correct according to the language semantics.
Then there is a third aspect of the semantics, that is "what does that construct mean?". You can see it as a correspondence between, for example, a for loop and how it is translated into the lower level language needed to be executed.
This third aspect will decide if your program is correct with respect to the allowed operations. Usually you can make a compiler reject many of programs that have no meaning (because they violates the semantic) but to be able to find many different mistakes you will have to introduce a new tool: the type checker that will also check that whenever you do operations they are correct according to the types.
For example you grammar can allow doing varName = 12.4 but the typechecker will use the declaration of varName to understand if you can assign a float to it. (of course we're talking about static type checking)
Those concepts belong to both.
Statements, expressions, control flow operations, data types, etc. have their structure defined using the syntax. However, their meaning comes from the semantics.
When you have defined syntax and semantics for a programming language and its constructs, this basically provides you with a set of building blocks. The syntax is used to understand the structure in the code - usually represented using an abstract syntax tree, or AST. You can then traverse the tree and apply the semantics to each element to execute the program, or generate some instructions for some instruction set so you can execute the code later.
In reading Haskell-related stuff I sometimes come across the expression “tying the knot”, I think I understand what it does, but not how.
So, are there any good, basic, and simple to understand explanations of this concept?
Tying the knot is a solution to the problem of circular data structures. In imperative languages you construct a circular structure by first creating a non-circular structure, and then going back and fixing up the pointers to add the circularity.
Say you wanted a two-element circular list with the elements "0" and "1". It would seem impossible to construct because if you create the "1" node and then create the "0" node to point at it, you cannot then go back and fix up the "1" node to point back at the "0" node. So you have a chicken-and-egg situation where both nodes need to exist before either can be created.
Here is how you do it in Haskell. Consider the following value:
alternates = x where
x = 0 : y
y = 1 : x
In a non-lazy language this will be an infinite loop because of the unterminated recursion. But in Haskell lazy evaluation does the Right Thing: it generates a two-element circular list.
To see how it works in practice, think about what happens at run-time. The usual "thunk" implementation of lazy evaluation represents an unevaluated expression as a data structure containing a function pointer plus the arguments to be passed to the function. When this is evaluated the thunk is replaced by the actual value so that future references don't have to call the function again.
When you take the first element of the list 'x' is evaluated down to a value (0, &y), where the "&y" bit is a pointer to the value of 'y'. Since 'y' has not been evaluated this is currently a thunk. When you take the second element of the list the computer follows the link from x to this thunk and evaluates it. It evaluates to (1, &x), or in other words a pointer back to the original 'x' value. So you now have a circular list sitting in memory. The programmer doesn't need to fix up the back-pointers because the lazy evaluation mechanism does it for you.
It's not quite what you asked for, and it's not directly related to Haskell, but Bruce McAdam's paper That About Wraps It Up goes into this topic in substantial breadth and depth. Bruce's basic idea is to use an explicit knot-tying operator called WRAP instead of the implicit knot-tying that is done automatically in Haskell, OCaml, and some other languages. The paper has lots of entertaining examples, and if you are interested in knot-tying I think you will come away with a much better feel for the process.