Is the following grammar is ambiguous and if it is What's the unambiguous grammar of the following - ambiguous-grammar

E-->I/E+E/E-E/E*E/E/E
I-->a/b/Ia/Ib/I0/I1
I know how to remove ambiguity for the productions of E but the presence of I is making me confuse to solve the ambiguity

Related

The Paterson Conditions for Type Checking in Haskell

Could someone please explain (or give me some examples or the process) on why are these conditions necessary for the termination of the instance resolution process in Haskell? Or at least a link where this algorithm is described.
For example, I tried to find some lecture about it, but I only can find stuff about type inference and not this instance resolution process.
I quote from Haskell User Guide
The rules are these:
The Paterson Conditions: for each class constraint (C t1 ... tn) in the context
No type variable has more occurrences in the constraint than in the head
The constraint has fewer constructors and variables (taken together and counting repetitions) than the head
The constraint mentions no type functions. A type function application can in principle expand to a type of arbitrary size, and
so are rejected out of hand
The Coverage Condition. For each functional dependency, ⟨tvs⟩left -> ⟨tvs⟩ right, of the class, every type variable in S(⟨tvs⟩right) must appear in S(⟨tvs⟩left), where S is the substitution mapping
each type variable in the class declaration to the corresponding type
in the instance head.
The so-called 'Paterson Conditions', used to guarantee that instance resolution terminates under the FlexibleInstances extension, are fully documented in Chapter 5 of the paper Understanding Functional Dependencies via
Constraint Handling Rules. Unfortunately, the discussion is quite technical and dense.
We could do with some gentler explanation giving an intuition as to what instances are legal; I've been trying to get my head around it for some time with no success.

Is Rust's syntactical grammar context-free or context-sensitive?

The syntactical grammar of hardly any programming language is regular, as they allow arbitrarily deeply nested parenthesis. Rust does, too:
let x = ((((()))));
But is Rust's syntactical grammar at least context-free? If not, what element makes the grammar context-sensitive? Or is the grammar even recursively enumerable, like C++'s syntactical grammar?
Related: Is Rust's lexical grammar regular, context-free or context-sensitive?
Rust includes a macro processor, whose operation is highly context-sensitive.
You could attempt to skate around this issue by only doing syntactic analysis up to but not including macro expansion -- possible, but not particularly useful -- or by assuming that the macro expansion is done by some intermediate tool which is given a free pass to allow it to be Turing complete.
But I'm inclined to say that it simply means that the Rust language is recursively enumerable.
There are a number of restrictions on the validity of macro definitions which probably make the language (at least) context-sensitive, even if you settle for not performing the macro expansions as part of syntactic analysis.
This doesn't mean that a context-free grammar cannot be useful as part of the syntactic analysis of Rust. It's probably essential, and it could even be useful to use a parser generator such as bison or Antlr (and examples of both exist). Like most programming languages, there is a simple superset of Rust which is context-free, and which can be usefully analysed with context-free grammar tools; however, in the end there are texts which will need to be rejected at compile-time as invalid even though they are part of the CF superset.
Answer straight from the source code for Rust:
Rust's lexical grammar is not context-free. Raw string literals are
the source of the problem. Informally, a raw string literal is an r,
followed by N hashes (where N can be zero), a quote, any characters,
then a quote followed by N hashes. Critically, once inside the first
pair of quotes, another quote cannot be followed by N consecutive
hashes. e.g. r###""###"### is invalid.

What is the grammar rule for this Haskell code?

I have basic knowledge of Haskell (so forgive me if my question looks trivial for Haskellers here) and recently have been looking into the syntax of Haskell. In the Haskell 2010 report there is only one place that keyword "type" is used:
topdecl ::= "type" simpletype "=" type
And as can be seen, there is always a "=" is required. In one Haskell file, I see this piece of code:
type Key m :: *
taken from TrieMap.hs line 61.
which doesn't comply to the rule. I suspect this is a GHC extension or something
similar. Can someone point out to me which grammar rule this piece of code conforms to?
BTW, I didn't find the grammar rules for extensions and had to guess many of them, are there documented somewhere?
That's an associated type family declaration, part of the TypeFamilies extension.
It's basically used inside a class declaration to tell that the class has a type associated to each instance of it.
I don't remember any place that has nicely laid out BNF grammar for extensions, although I did once find GHC's Happy grammar in its repository.

Why does GHC typecheck before desugaring?

Is there a good reason to run the typechecker first? It would seem that the typechecker would be vastly simpler if it ran on a smaller syntax, especially because with the current system every syntax extension needs to touch the typechecker. This question applies especially to arrow syntax, the typechecking of which as described in comments here is known to be bogus.
I imagine one reason for this would be not emitting errors that mention generated code, but this situation is already covered in cases where a deriving clause fails to typecheck; GHC knows that code was generated.
There is a section on this question in the GHC article found in volume 2 of the book "The Architecture of Open Source Application":
Type Checking the Source Language
One interesting design decision is
whether type checking should be done before or after desugaring. The
trade-offs are these:
Type checking before desugaring means that the type checker must deal
directly with Haskell's very large syntax, so the type checker has
many cases to consider. If we desugared into (an untyped variant of)
Core first, one might hope that the type checker would become much
smaller.
On the other hand, type checking after desugaring would
impose a significant new obligation: that desugaring does not affect
which programs are type-correct. After all, desugaring implies a
deliberate loss of information. It is probably the case that in 95% of
the cases there is no problem, but any problem here would force some
compromise in the design of Core to preserve some extra information.
Most seriously of all, type checking a desugared program would make it
much harder to report errors that relate to the original program text,
and not to its (sometimes elaborate) desugared version.
Most compilers type check after desugaring, but for GHC we made the opposite choice:
we type check the full original Haskell syntax, and then desugar the
result. It sounds as if adding a new syntactic construct might be
complicated, but (following the French school) we have structured the
type inference engine in a way that makes it easy. Type inference is
split into two parts:
Constraint generation: walk over the source syntax tree, generating a
collection of type constraints. This step deals with the full syntax
of Haskell, but it is very straightforward code, and it is easy to add
new cases.
Constraint solving: solve the gathered constraints. This is
where the subtlety of the type inference engine lies, but it is
independent of the source language syntax, and would be the same for a
much smaller or much larger language.
On the whole, the
type-check-before-desugar design choice has turned out to be a big
win. Yes, it adds lines of code to the type checker, but they are
simple lines. It avoids giving two conflicting roles to the same data
type, and makes the type inference engine less complex, and easier to
modify. Moreover, GHC's type error messages are pretty good.

What is a good reason to use a type signature for functions when the compiler can infer the types

I am trying to code using 'good Haskell style' and so am trying to follow typical coding standards I find around. Also, compiling with -Wall and -Werror as I am used to when coming from C. One of the warnings I frequently get is "Top level binding with no type signature" and then the compiler tells me what the type signature should be.
I am missing what the advantage of having the type signature explicitly defined is. As a concrete example:
-- matchStr :: String -> String -> Maybe (String)
matchStr str s
| isPrefixOf str s = Just(drop (length str) s)
| otherwise = Nothing
Now what happens if I want to change the type from String to ByteString to improve performance; I'll have to import the ByteString package and use a qualified version of some functions. No other changes are necessary. If I have the type signature then I also have to change this and yet the Haskell compiler would notice this change and correctly infer the new types.
So what am I missing? Why is it considered a good idea to explicitly put type signatures on functions in the general case? i.e. I understand that there might be exceptions where it is a good idea, but why is it considered good in general?
If you make a mistake in defining your function, the compiler might infer a type that isn't what you expected it to be. If you've declared the type you expect, the compiler will report the error in the function's definition.
Without the declaration, the compiler has no way to know that its inferred type is "wrong", and it will instead end up reporting errors in the places where you try to call the function, which makes it less clear where the problem really lies.
If the calling functions don't have type declarations either, then instead of reporting errors there, the compiler might just infer incorrect types for those too, causing problems in their callers. You'll end up getting an error message somewhere, but it may be quite far removed from the actual root of the problem.
Also, you can declare a more specific type than what the compiler would infer. For example, if you write the function:
foo n = n + 1
The compiler will infer the type Num a => a -> a, which means it must compile generic code that can work with any Num instance. If you declare the type as Int -> Int, the compiler may be able to produce more efficient code that's specialized for integers only.
Finally, type declarations serve as documentation. The compiler may be able to infer the types of complex expressions, but it's not so easy for a human reader. A type declaration provides the "big picture" that can help a programmer understand what the function does.
Note that Haddock comments are attached to declarations, not definitions. Writing a type declaration is the first step toward providing additional documentation for a function using Haddock.
I would consider documentation one advantage of having an explicit type signature.
From "Types and Programming Languages":
Types are also useful when reading programs. The type declarations in procedure headers and module interfaces constitute a form of documentation, giving useful hints about behavior. Moreover, unlike descriptions embedded in comments, this form of documentation cannot become outdated, since it is checked during every run of the compiler. This role of types is particularly
important in module signatures.
There are several reasons.
It may make the code easier for humans to read. (OTOH, if you have dozens of tiny definitions, sometimes the type signatures add more clutter.)
If your implementation is wrong, the compiler may infer the wrong type. This may cause other functions' types to be inferred wrong, finally resulting in a type error very far away from the actual broken function.
You may want to give a function a less polymorphic type than it could have, for performance reasons.
You may want to use type aliases. This allows you to quickly change a type in several places, and also to document some of the intent behind a value. (Compare FilePath vs String.)
The compiler can figure out types automatically, but not all external tools can do this. (E.g., originally Haddock would refuse to produce documentation for functions lacking an explicit type signature - although I gather this is fixed now.)
It is worth noting that some people advocate that you start with the type signatures, and fill in the implementations later.
At any rate, most people seem to recommend type signatures for all or most top-level declarations. Whether you give them for local variables / functions is a matter of taste.
Your contrived example is really contrived, since the function body does not depend on the type of contents of the list. In this case it is indeed difficult to see what's the benefit of defining the type to be [String] -> ([String],[String]) instead of [a]->([a],[a])
If you attempt to define a function that depends on the contents, you will see that the type definition is not the only thing you need to change. For example, changing a list for MArray is going to be far more involved, not just using a function that happens to have the same name in a different module. So qualifying the name during refactoring in a few narrow cases is not a good enough reason to not specify type signatures.
Specifying the type tells the compiler a little bit of the intent. Then the compiler will be able to report the mismatch of the intent and the implementation.

Resources