Re: [Haskell-cafe] Documenting the impossible

2008-06-15 Thread Evan Laforge
> Hmm, this gives me a new idea for a feature request - how about a function
> that evaluates to the source code line number it was called from? ;-)

Well, that wouldn't be a function, but one of the other "-hc"s (j? n?)
has srcloc_annotate which is a macro that does that.  It would be nice
if ghc had it.  Meanwhile, I use -pgmF to replace certain functions
with *_srcloc ones that pass a SrcLoc argument, and it works mostly
ok.  I don't know what other people do, but having file:line in logs
and test failures is pretty handy.

Only "mostly" because it replaces things in strings, because I can't
use cpp because it doesn't understand dots in identifiers, and can't
use Language.Haskell.Parser because it *also* doesn't understand dots
in identifiers, so it's Regex.subRegex (speaking of not being designed
for qualified import...) until I get around to doing it with parsec.
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Documenting the impossible

2008-06-15 Thread Henning Thielemann


On Sun, 15 Jun 2008, Andrew Coppin wrote:


Henning Thielemann wrote:
I think it is another instance of mixing up errors and exceptions (you know 
the haskellwiki pages ...)


Since an 'error' marks a programming error (which should never occur) it 
would not hurt the program if all 'error's are replaced by 'undefined', an 
illegal memory access or any other misbehaviour. So 'error' is exactly what 
you propose as IMPOSSIBLE pragma. A compiler option for replacing all 
'error's by nops would do want you want.


OK, so suppose I write a module that contains a function that accepts a 
number parameter, and that parameter must be greater than 2. I have no 
control over what value users of the library pass to my function. Suppose 
some client calls my function with 1 as an argument - is that an error, or an 
exception?


It's an error, like 'head []' is an error. You must document the condition 
(argument > 2), unfortunately Haskell's type system does not allow to 
state such conditiions conveniently, and then it's the caller's 
responsibility to ensure that the argument is greater than 2.
 I like to distinguish between two kinds of users. (Are there common names 
for them?) The (consumer) user communicates with your program via an 
interface you provide: A GUI, the command line, a network. The user may 
even not know, that the program is written in Haskell. Everything this 
user makes wrong is an exception. You cannot forbid the user to make 
something wrong. The other kind of users are programmers, who call 
functions of your library. This interface is especially fast but in order 
to get the efficiency you can expect some cooperation by the programmer. 
E.g. the programmer of your library must ensure that the argument is 
always greater than 2. Otherwise _he_ has done an _error_.
 However if he writes a program which lets the user enter the number in a 
GUI dialog which is then passed to your library, then he must check the 
number before forwarding it, because the user can do wrong things. If the 
user enters '1' this is an _exception_. If the programmer does not reject 
this input it is an error.


On the other hand, suppose I write the same function, but now it's not 
exported. So the only code that can possibly call this function is my own 
code. So I can [theoretically] guarantee it will never be called with the 
"wrong" argument [assuming the code I write isn't defective].


As far as I can tell, there's no way of making this distinction in Haskell 
code. You'd use "error" in both cases - or if you're feeling brave, remove it 
in the second case and hope you're right. I'm just saying it would be nice to 
be able to keep it in the code for maintainability's sake, but not have the 
runtime penalty for it once you're "sure" your code is safe.


In theory you could remove 'error' in both cases, because in theory 
neither you nor the library user makes mistakes. In practice you better 
leave the error, because both of you actually make mistakes.


It looks like Don's "assert" thing might be able to do this. [I had no idea 
this existed by the way...]


As far as I understand, 'assert' is a wrapper to 'error' which also 
determines the source code location without using the C preprocessor. Is 
this correct?


Hmm, this gives me a new idea for a feature request - how about a function 
that evaluates to the source code line number it was called from? ;-)


Would be also nice for a "single stepper", which shows at which places in 
the source code things are currently evaluated.

___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Documenting the impossible

2008-06-15 Thread Andrew Coppin

Henning Thielemann wrote:
I think it is another instance of mixing up errors and exceptions (you 
know the haskellwiki pages ...)


Since an 'error' marks a programming error (which should never occur) 
it would not hurt the program if all 'error's are replaced by 
'undefined', an illegal memory access or any other misbehaviour. So 
'error' is exactly what you propose as IMPOSSIBLE pragma. A compiler 
option for replacing all 'error's by nops would do want you want.


OK, so suppose I write a module that contains a function that accepts a 
number parameter, and that parameter must be greater than 2. I have no 
control over what value users of the library pass to my function. 
Suppose some client calls my function with 1 as an argument - is that an 
error, or an exception?


On the other hand, suppose I write the same function, but now it's not 
exported. So the only code that can possibly call this function is my 
own code. So I can [theoretically] guarantee it will never be called 
with the "wrong" argument [assuming the code I write isn't defective].


As far as I can tell, there's no way of making this distinction in 
Haskell code. You'd use "error" in both cases - or if you're feeling 
brave, remove it in the second case and hope you're right. I'm just 
saying it would be nice to be able to keep it in the code for 
maintainability's sake, but not have the runtime penalty for it once 
you're "sure" your code is safe.


It looks like Don's "assert" thing might be able to do this. [I had no 
idea this existed by the way...]


Hmm, this gives me a new idea for a feature request - how about a 
function that evaluates to the source code line number it was called 
from? ;-)


___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Documenting the impossible

2008-06-15 Thread Richard Kelsall

Andrew Coppin wrote:
Obviously there is no way in hell this code path can ever be executed. 


Ah, the number of times I've thought that and been wrong :)

From a simplistic perspective what I think you're asking for is
to have obscure occasions when your program goes wrong with random
consequences and doesn't give you an error message. This a programmer's
worst nightmare. I can think of several dimensions of bug difficulty

When the bug exhibits:
  Hard   : Infrequent at run-time.
  Medium : Frequent at run-time.
  Easy   : Compile-time.

Reproducible:
  Hard   : No obvious pattern or way to induce the error.
  Medium : A reasonably strong correlation with some precursor.
  Easy   : Happens every time you do a particular thing.

Error message:
  Hard   : No error message.
  Medium : Non-specific error message.
  Easy   : Error message that relates to an identifiable
   point in your program with relevant state information.

Error message location:
  Medium : Appears on the screen.
  Easy   : Shown on screen and recorded in a log file.

Where it happens:
  Hard   : Only on your user's machine or with their configuration.
  Easy   : On all machines.


By classifying error messages, for bugs which you have stated are
infrequent and difficult to reproduce, as not needing to be displayed
or logged you have pushed all these bugs into the seriously hard
category. By adding 'undefined' subsequent behaviour you have made
these bugs even more difficult. What we should be doing is pushing
every bug in the opposite direction - towards the easy end of all
the above dimensions.


Richard.
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Documenting the impossible

2008-06-14 Thread Isaac Dupree

Neil Mitchell wrote:

* abort - deliberate aborting because the user made some mistake.

 This is an exception. The signature of a function must reflect this by a
Maybe, Either type etc.


Disagree. I mean more like:

when (Delete `elem` flags && Keep `elem` flags) $
   abort "User cannot pick both keep and delete on the command line"

Think "die" in Perl world.


in that case should use abort :: String -> IO a, not abort :: String -> 
a.  "abort" as "pure function" is just for messy scripting convenience 
a-la Perl.  (Which is not to say that's never useful, of course -- I 
would just try my hardest to avoid it in my code, probably.)


On the other hand, Control.Exception.throw, if it's ever useful, 
obviously isn't meant to indicate a programmer error, but to throw an 
exception (that will probably be caught somewhere in the program's IO). 
 So there's a reason for _|_ besides programmer error (well, there's 
also user-driven nontermination such as when an interpreter is told to 
execute an infinite loop :-)


-Isaac
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Documenting the impossible

2008-06-14 Thread Henning Thielemann


On Sat, 14 Jun 2008, Neil Mitchell wrote:


Hi


* error - inserted by the compiler


 Example?


Pattern-match errors.


Calling a function with patterns it cannot process is a programming error.


* abort - deliberate aborting because the user made some mistake.


 This is an exception. The signature of a function must reflect this by a
Maybe, Either type etc.


Disagree. I mean more like:

when (Delete `elem` flags && Keep `elem` flags) $
  abort "User cannot pick both keep and delete on the command line"

Think "die" in Perl world.


I wouldn't use such a function, because it does not scale. E.g. I cannot 
code a loop which lets the user enter flags until they match the 
conditions. Thus instead of 'abort' I would throw an exception - which is 
equivalent to the use of an exceptional value like Nothing or Left in 
Haskell (maybe wrapped in ErrorT).

___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Documenting the impossible

2008-06-14 Thread Neil Mitchell
Hi

> > * error - inserted by the compiler
>
>  Example?

Pattern-match errors.

> > * abort - deliberate aborting because the user made some mistake.
>
>  This is an exception. The signature of a function must reflect this by a
> Maybe, Either type etc.

Disagree. I mean more like:

when (Delete `elem` flags && Keep `elem` flags) $
   abort "User cannot pick both keep and delete on the command line"

Think "die" in Perl world.

Thanks

Neil
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Documenting the impossible

2008-06-14 Thread Henning Thielemann


On Sat, 14 Jun 2008, Neil Mitchell wrote:


Hi


 How about a {-# IMPOSSIBLE #-} pragma that documents the fact that a
particular point in the program *should* be unreachable?


Why not make it a function taking a string and returning a value of
any type. Then we can keep our language and not break various
parsing/type checking properties and rules on pragmas. We can even
define it:

impossible = error

Now you can use tools like Catch and Reach to ensure it is impossible.

I think it would be nice to distinguish between:

* error - inserted by the compiler


Example?


* impossible - the programmer knows this can't occur


This is an error. However the programmer adds a message because he might 
be wrong.



* abort - deliberate aborting because the user made some mistake.


This is an exception. The signature of a function must reflect this by a 
Maybe, Either type etc.



http://www.haskell.org/haskellwiki/Exception
http://www.haskell.org/haskellwiki/Error
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Documenting the impossible

2008-06-14 Thread Marc Weber
>  Does anybody think this is a useful idea? If so I'll add a feature request 
>  ticket to the GHC Trac. But I want to see if folks like the idea first...

Mmmh.. dont' know. Even Java folks don't allow this kind of creeping
bug and I guess they know why. You never want undefined behaviour at
least when using haskell. Because if that error occurs it's hard to
debug, no I don't like that at all.

May I look at your proposal from another view?
Am I right that you ask for not having to run the "fromJust" code to
save some cpu cycles?

Very simple example : 
let list = [ (a,a*a) | a <- [1..10] ]
in ..

Now getting the square of 4 (standard)
fromJust $ lookup 4 list

Removing the fromJust code thingy leads to:

lookupGoodFaith key ((x,v):xs) | key == x = v
   | otherwise = lookupGoodFaith xs
lookupGoodFaith _ (_,v) = v

Where is the difference? I don't even compare the key of the last list
item, because it must match. So you safe some additional cpu cycles..
The same can be implemented for Data.Map etc..

Marc Weber
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Documenting the impossible

2008-06-14 Thread Neil Mitchell
Hi

>  How about a {-# IMPOSSIBLE #-} pragma that documents the fact that a
> particular point in the program *should* be unreachable?

Why not make it a function taking a string and returning a value of
any type. Then we can keep our language and not break various
parsing/type checking properties and rules on pragmas. We can even
define it:

impossible = error

Now you can use tools like Catch and Reach to ensure it is impossible.

I think it would be nice to distinguish between:

* error - inserted by the compiler
* impossible - the programmer knows this can't occur
* abort - deliberate aborting because the user made some mistake.

The safe library provides abort already.

Thanks

Neil
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Documenting the impossible

2008-06-14 Thread Don Stewart
andrewcoppin:
> I have a small idea. I'm curios if anybody else thinks it's a good idea...
> 
> How about a {-# IMPOSSIBLE #-} pragma that documents the fact that a 
> particular point in the program *should* be unreachable?
> 
> For example, you look up a key in a Map. You know the key is there, 
> because you just put it there yourself two seconds ago. But, 
> theoretically, lookup returns a Maybe x so - theoretically - it's 
> possible it might return Nothing. No matter what you do, GHC will insert 
> code to check whether we have Just x or Nothing, and in the Nothing case 
> throw an exception.
> 
> Obviously there is no way in hell this code path can ever be executed. 
> At least, assuming your code isn't broken... This is where the pragma 
> comes in. The idea is that you write something like
> 
>  case lookup k m of
>Just v -> process v
>Nothing -> {-# IMPOSSIBLE "lookup in step 3" #-}

You could try using an 'assert' , which has the property of being
compiled out at higher optimisation levels. And you can use 'error' or
'undefined' for undefined behaviour.

http://www.haskell.org/ghc/docs/latest/html/users_guide/assertions.html

Not very Haskelly though.

-- Don
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Documenting the impossible

2008-06-14 Thread Thomas M. DuBuisson
I think when Andy made HPC he added a way to mark code unreachable so it
wouldn't "harm" your test coverage report.


On Sat, 2008-06-14 at 19:58 +0100, Andrew Coppin wrote:
> I have a small idea. I'm curios if anybody else thinks it's a good idea...
> 
> How about a {-# IMPOSSIBLE #-} pragma that documents the fact that a 
> particular point in the program *should* be unreachable?
> 
> For example, you look up a key in a Map. You know the key is there, 
> because you just put it there yourself two seconds ago. But, 
> theoretically, lookup returns a Maybe x so - theoretically - it's 
> possible it might return Nothing. No matter what you do, GHC will insert 
> code to check whether we have Just x or Nothing, and in the Nothing case 
> throw an exception.
> 
> Obviously there is no way in hell this code path can ever be executed. 
> At least, assuming your code isn't broken... This is where the pragma 
> comes in. The idea is that you write something like
> 
>   case lookup k m of
> Just v -> process v
> Nothing -> {-# IMPOSSIBLE "lookup in step 3" #-}
> 
> When compiled without optimisations, the pragma just causes an exception 
> to be thrown, rather like "error" does. When compiled with 
> optimisations, the whole case alternative is removed, and no code is 
> generated for it. (And if the impossible somehow happens... behaviour is 
> undefined.) So you test your program with your code compiled 
> unoptimised, and when you're "sure" the impossible can't happen, you 
> tell the compiler to remove the check for it. (Actually, it would 
> possibly be a good idea to have a switch to turn this on and off 
> seperately if needed...)
> 
> Does anybody think this is a useful idea? If so I'll add a feature 
> request ticket to the GHC Trac. But I want to see if folks like the idea 
> first...
> 
> (I was thinking the message in the pragma would be what gets displayed 
> on screen, along with some auto-generated location info. Just a module 
> name and line number ought to be sufficient...)
> 
> ___
> Haskell-Cafe mailing list
> Haskell-Cafe@haskell.org
> http://www.haskell.org/mailman/listinfo/haskell-cafe


signature.asc
Description: This is a digitally signed message part
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Documenting the impossible

2008-06-14 Thread Henning Thielemann


On Sat, 14 Jun 2008, Andrew Coppin wrote:

How about a {-# IMPOSSIBLE #-} pragma that documents the fact that a 
particular point in the program *should* be unreachable?

...
When compiled without optimisations, the pragma just causes an exception to 
be thrown, rather like "error" does. When compiled with optimisations, the 
whole case alternative is removed, and no code is generated for it. (And if 
the impossible somehow happens... behaviour is undefined.) So you test your 
program with your code compiled unoptimised, and when you're "sure" the 
impossible can't happen, you tell the compiler to remove the check for it. 
(Actually, it would possibly be a good idea to have a switch to turn this on 
and off seperately if needed...)


I think it is another instance of mixing up errors and exceptions (you 
know the haskellwiki pages ...)


Since an 'error' marks a programming error (which should never occur) it 
would not hurt the program if all 'error's are replaced by 'undefined', an 
illegal memory access or any other misbehaviour. So 'error' is exactly 
what you propose as IMPOSSIBLE pragma. A compiler option for replacing all 
'error's by nops would do want you want.

___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Documenting the impossible

2008-06-14 Thread Derek Elkins
On Sat, 2008-06-14 at 19:58 +0100, Andrew Coppin wrote:
> I have a small idea. I'm curios if anybody else thinks it's a good idea...
> 
> How about a {-# IMPOSSIBLE #-} pragma that documents the fact that a 
> particular point in the program *should* be unreachable?
> 
> For example, you look up a key in a Map. You know the key is there, 
> because you just put it there yourself two seconds ago. But, 
> theoretically, lookup returns a Maybe x so - theoretically - it's 
> possible it might return Nothing. No matter what you do, GHC will insert 
> code to check whether we have Just x or Nothing, and in the Nothing case 
> throw an exception.
> 
> Obviously there is no way in hell this code path can ever be executed. 
> At least, assuming your code isn't broken... This is where the pragma 
> comes in. The idea is that you write something like
> 
>   case lookup k m of
> Just v -> process v
> Nothing -> {-# IMPOSSIBLE "lookup in step 3" #-}
> 
> When compiled without optimisations, the pragma just causes an exception 
> to be thrown, rather like "error" does. When compiled with 
> optimisations, the whole case alternative is removed, and no code is 
> generated for it. (And if the impossible somehow happens... behaviour is 
> undefined.) So you test your program with your code compiled 
> unoptimised, and when you're "sure" the impossible can't happen, you 
> tell the compiler to remove the check for it. (Actually, it would 
> possibly be a good idea to have a switch to turn this on and off 
> seperately if needed...)
> 
> Does anybody think this is a useful idea? If so I'll add a feature 
> request ticket to the GHC Trac. But I want to see if folks like the idea 
> first...
> 
I think it's a horrible idea.

___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe