Let's say I would generally like to be warned about incomplete patterns in my code, but sometimes I know about a pattern incompleteness for a certain function and I know it's fine.
Is it still true that GHC's warning granularity is per-module, and there's no way to change warnings regarding a particular function or definition?
Yes, still true, but you can work around this by using error.
f (Just a) = show a
without a case for Nothing gives warnings but adding
f Nothing = error "f: Nothing supplied as an argument. This shouldn't have happened. Oops."
gets rid of the warning.
A per-function solution of your problem is to give Haskell some code you think will never be run, to keep it quiet.
Please note: I think your code should be robust and cover every eventuality unless you can prove it will never happen.
Working around this restriction isn't very good practice, I think.
(You might think that is a wide-open back door to hack away a useful compile-time check and should be stopped by -Wall, but I can obfuscate my round any simple restriction you'd choose and I think a complete solution to that problem would essentially solve the halting problem, so let's not blame the compiler.)
Related
A grammar (copied from its manual) reports the following left recursions when
I un-commented the following production: casting_type->constant_primary
error(119): The following sets of rules are mutually left-recursive [primary, method_call_root, method_call, cast]
and [casting_type, constant_cast, cast, constant_primary, constant_function_call, function_subroutine_call, primary]
and [subroutine_call, function_subroutine_call, constant_function_call, constant_primary, method_call, method_call_root, casting_type, primary, constant_cast, cast]
The above error report has 3 sets of rules. The third set has 2 left-recursions in it:
casting_type,constant_primary,constant_cast,casting_type
casting_type,constant_primary,constant_function_call,function_subroutine_call,subroutine_call,method_call,method_call_root,primary,cast,casting_type
Since this error was reported after I un-commented one production, I
think it is reasonable to expect to see at least its names in each set (casting_type,constant_primary). Clearly the first set
lacks both these names, so it cannot contain a recursion. And the second set (I cannot give the full
grammar here because it is too long) has recursion-1 and some extra names
which seem not relevant.
My question is: why is Antlr printing the first and the second sets of rules?
Is this a bug in antlr (I tried 4.6 and 4.7, same result), or is this hinting at a problem that I am missing something in these sets?
I saw a similar post elsewhere, where the reported names did not indicate a recursion, but on deeper analysis recursion was found somewhere else.
Probably nobody can really answer your question, not even the authors of ANTLR. To me it looks like you get follow-up errors which make not much sense, because a real error made analysis impossible (or at least can lead to wrong conclusions). Of course there can also be a bug in ANTLR, but I recommend to focus on one of the sets and fix that (if you can see what makes them mutually left recursive). Maybe the other errors disappear then or you have to analyze again.
I've been wanting to make a block type game for a while now but have never understood how to actually make one. I have googled forever and there is not much and what is there comes with a stipulation that I am not wanting to bother with (gpl license, entire code base, AND the license in any project, bleh). So I took to a forums with my problem. I did not know it, but I was trying to make a Puyo Puyo type game. With blocks dropping from the ceiling and then clearing if there's a match of 3 or more. I had no idea on how to do the matching. Which is what I wanted to know. A very nice, charming, and intelligent fellow provided me with this:
http://hastebin.com/ziyejejoxu.js
Granted, that's quite a lot, but the way he managed to code it allowed me to somewhat grasp it. However, there is a single infuriating problem. One, exactly ONE, line of code does not compile and breaks. I asked him if I could email him about it and he said okay. I haven't go a response yet so I may not be getting one so I'm taking this here. Here is how I am using the code so far. There are two parts, the play state, and the puzzle piece:
http://pastebin.com/SvMR9mMb
The program breaks in the playstate, giving this error:
source/PlayState.hx:291: characters 33-52 : Array access is not allowed on x : Int -> Int
What I have tried:
I had assumed that it was not allowed because the puzzle piece x is a float, and of course, you can't push a float into an int array. So what I did was simply in the puzzle piece first, convert the the float to an int. That did not work. THEN in the state, I switched the float to an int. That did not work. As an exercise, I attempted to convert a Flixel game to HaxeFlixel to see if I could learn anything. I probably did it wrong and did not.
So the question is: Why does that line not compile and what do I need to do to make it compile or to achieve it's intended purpose?
The syntax is wrong. push is a function, and function calls use (). [] is for array access (hence the error message).
This should work:
if (this_piece_is_in_a_match) matched_pieces.push(_i);
Is it possible to disable or work around the type system in Haskell? There are situations where it is convenient to have everything untyped as in Forth and BCPL or monotyped as in Mathematica. I'm thinking along the lines of declaring everything as the same type or of disabling type checking altogether.
Edit: In conformance with SO principles, this is a narrow technical question, not a request for discussion of the relative merits of different programming approaches. To rephrase the question, "Can Haskell be used in a way such that avoidance of type conflicts is entirely the responsibility of the programmer?"
Also look at Data.Dynamic which allows you to have dynamically typed values in parts of your code without disabling type-checking throughout.
GHC 7.6 (not released yet) has a similar feature, -fdefer-type-errors:
http://hackage.haskell.org/trac/ghc/wiki/DeferErrorsToRuntime
It will defer all type errors until runtime. It's not really untyped but it allows almost as much freedom.
Even with fdefer-type-errors one wouldn't be avoiding the type system. Nor does it really allow type independence. The point of the flag is to allow code with type errors to compile, so long as the errors are not called by the Main function. In particular, any code with a type error, when actually called by a Haskell interpreter, will still fail.
While the prospect of untyped functions in Haskell might be tempting, it's worth noting that the type system is really at the heart of the language. The code proves its own functionality in compilation, and the rigidity of the type system prevents a large number of errors.
Perhaps if you gave a specific example of the problem you're having, the community could address it. Interconverting between number types is something that I've asked about before, and there are a number of good tricks.
Perhaps fdefer-type-errors combined with https://hackage.haskell.org/package/base-4.14.1.0/docs/Unsafe-Coerce.html offers what you need.
I'm working on a simple programming language for kids, based on Karel. For controlling program flow, I currently provide these facilities (in pseudocode):
defining parameterless procedures
if [not] EXPRESSION STATEMENT
while [not] EXPRESSION STATEMENT
I don't have any means to return from a procedure, and I don't provide the else statement.
Take the following code for an example:
if something
statement1
if not something
statement2
The execution of code flows to if, executing statement1 if something is true;
then testing if something is not true (but the state of the program has changed!), then executing statement2. This can lead to both tests succeeding.
Does this limit the programmer? So far I've been able to solve all of my example problems by just using if ... if not ..., or using if not first, then if.
So, my question is:
Is adding the else statement necessary? It would make the language a bit more complicated with having more keywords. Are all problems that would be solvable with else statement solvable also without it, albeit more complicated?
Or is omitting the else statement actually making the language more complicated and counter-intuitive?
If something is expensive to evaluate then your language with else might give a problem because the evaluation will be performed twice.
Another potential problem is that if statement1 can modify the value of something you may end up with both tests succeeding - something that could not happen if you used else.
Of course these problems can be mitigated by storing the result in a temporary local variable:
bool result = something
if result
statement1
if not result
statement2
So no you aren't limiting the programmer in what is possible - everything that can be done with else can be done without it by using the above approach. But it is a little more code to write each time and it introduces a few new potential problems for the unwary programmer that would be avoided if you allowed else.
Semantically speaking you could avoid having the else construct, but from practical point of view I don't see any necessity of doing that.
The concept of do something if something is true, otherwise something else is not so strange and confusing, it sounds actually quite straightforward that having to evaluate and negate an expression again just to check its negation.. it's a free (in sense of "with no added complexity") optional synctactic sugar that is automatic when developing a language.
I saw many other features really more useless compared to the else statement.. then you are not considering the fact that evaluating a condition twice maybe harmful for side-effects or for complexity (wasted cpu?) or for the fact itself that you already have calculated it and you have to do it again for a lack of the language not because it's senseful.
If something has side-effects than your approach will cause them to happen twice, which is probably not what you want.
IMHO It's bad idea to teach children to duplicate code.
Is it generally considered a bad practice to use non-exhaustive pattern machings in functional languages like Haskell or F#, which means that the cases specified don't cover all possible input cases?
In particular, should I allow code to fail with a MatchFailureException etc. or should I always cover all cases and explicitly throw an error if necessary?
Example:
let head (x::xs) = x
Or
let head list =
match list with
| x::xs -> x
| _ -> failwith "Applying head to an empty list"
F# (unlike Haskell) gives a warning for the first code, since the []-case is not covered, but can I ignore it without breaking functional style conventions for the sake of succinctness? A MatchFailure does state the problem quite well after all ...
If you complete your pattern-matchings with a constructor [] and not the catch-all _, the compiler will have a chance to tell you to look again at the function with a warning the day someone adds a third constructor to lists.
My colleagues and I, working on a large OCaml project (200,000+ lines), force ourselves to avoid partial pattern-matching warnings (even if that means writing | ... -> assert false from time to time) and to avoid so-called "fragile pattern-matchings" (pattern matchings written in such a way that the addition of a constructor may not be detected) too. We consider that the maintainability benefits.
Explicit is better than implicit (borrowed from the Zen of Python ;))
It's exactly the same as in a C switch over an enum... It's better to write all the cases (with a fall through) rather than just putting a default, because the compiler will tell you if you add new elements to the enumeration and you forgot to handle them.
I think that it depends quite a bit on the context. Are you trying to write robust, easy to debug code, or are you trying to write something simple and succinct?
If I were working on a long term project with multiple developers, I'd put in the assert to give a more useful error message. I also agree with Pascal's comment that not using a wildcard would be ideal from a software engineering perspective.
If I were working on a smaller scale project on which I was the only developer, I wouldn't think twice about using an incomplete match. If necessary, you can always check the compiler warnings.
I think it also depends a bit on the types you're matching against. Realistically, no extra union cases will be added to the list type, so you don't need to worry about fragile matching. On the other hand, in code that you control and are actively working on, there may well be types which are in flux and have additional union cases added, which means that protecting against fragile matching may be worth it.
This is a special case of a more general question, which is "should you ever create partial functions". Incomplete pattern matches are only one example of partial functions.
As a rule total functions are preferable. When you find yourself looking at a function that just has to be partial, ask yourself if you can solve the problem in the type system first. Sometimes that is more trouble than its worth (e.g. creating a whole type of lists with known lengths just to avoid the "head []" problem). So its a trade-off.
Or maybe you just asking whether its good practice in partial functions to say things like
head [] = error "head: empty list"
In which case the answer is YES!
The Haskell prelude (standard functions) contains many partial functions, e.g. head and tail only work on non-empty lists, but don't ask me why.
This question has two aspects.
For the user of the API, failwith... simply throws a System.Exception, which is unspecific (and therefore is sometimes considered a bad practice in itself). On the other hand, the implicitly thrown MatchFailureException can be specifically caught using a type test pattern, and therefore is preferrable.
For the reviewer of the implementation code, failwith... clearly documents that the implementer has at least given some thought about the possible cases, and therefore is preferrable.
As the two aspects contradict each other, the right answer depends on the circumstances (see also kvb's answer). A solution which is 100% "correct" from any point of view would have to
deal with every case explicitly,
throw a specific exception where necessary, and
clearly document the exception
Example:
/// <summary>Gets the first element of the list.</summary>
/// <exception cref="ArgumentException">The list is empty.</exception>
let head list =
match list with
| [] -> invalidArg "list" "The list is empty."
| x::xs -> x