[Haskell-cafe] Re: Debugging partial functions by the rules
Donald Bruce Stewart wrote: So all this talk of locating head [] and fromJust failures got me thinking: Couldn't we just use rewrite rules to rewrite *transparently* all uses of fromJust to safeFromJust, tagging the call site with a location? I'm sorry for shifting the topic: I'm wondering if, rather than trying to make an error message more informative, we ought to make sure that no error will ever arise? The fromJust and `head of empty list' errors are totally equivalent to the dereferencing of zero pointer in C++ or NullPointerException in Java. It pains me to see that exactly the same problem arises in Haskell -- keeping in mind that already in C++ and Java one may exterminate these errors given right encapsulations. Languages like Cyclone or Cw use the type system to eliminate such errors. Surely Haskell can do something about this? This topic has been discussed at length on this list. It seems that the discussion came to the conclusion that eliminating head of the empty list error is possible and quite easy in Haskell. http://www.haskell.org/pipermail/haskell-cafe/2006-September/017915.html http://www.haskell.org/pipermail/haskell-cafe/2006-September/017937.html As to fromJust: would the world come to an end if this function is just not available? Oftentimes when we get the value of the type |Maybe a|, the algorithm prescribes the actions for the case if this value is Nothing. Thus the function `maybe', the deconstructor, seems to be called for. And if we are dead sure that the |Maybe a| value is definitely |Just smth| and we need to extract this |smth|, we can always write maybe (assert False undefined) id value I like how this phrase stands out in the code, to remind me to double-check my certainty about the value (and perhaps, to re-factor the code). Similarly for empty lists: it is often algorithmically significant as it is the base case for our recursion/induction. Thus, we have to make the null check according to the algorithm anyway. The type system can carry the result of such a test, so we don't have to repeat it. The functions head and tail should operate on the newtype NonemptyList -- in which case they are total. Other list functions may remain as they are, because we can always `forget' the NonemptyList tag. The run-time overhead is zero, the notational overhead is not much: writing a few extra `fromNonemptyList'. Compare with writing `fromIntegral', especially in the FFI-related code. The Haskell type system can do far more complex things, for example, solve the pervasive SQL injections and cross-site scripting problems: http://blog.moertel.com/articles/2006/10/18/a-type-based-solution-to-the-strings-problem (This URL appeared on one of the recent Haskell Weekly News, btw). Surely we can do something about a far simpler problem of head [] and fromJust? We may have to adjust our coding styles a little. The adjustment doesn't appear extensive; besides, isn't the whole point of programming in Haskell is to think differently? ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: Debugging partial functions by the rules
oleg: Donald Bruce Stewart wrote: So all this talk of locating head [] and fromJust failures got me thinking: Couldn't we just use rewrite rules to rewrite *transparently* all uses of fromJust to safeFromJust, tagging the call site with a location? I'm sorry for shifting the topic: I'm wondering if, rather than trying to make an error message more informative, we ought to make sure that no error will ever arise? The fromJust and `head of empty list' errors are totally equivalent to the dereferencing of zero pointer in C++ or NullPointerException in Java. It pains me to see that exactly the same problem arises in Haskell -- keeping in mind that already in C++ and Java one may exterminate these errors given right encapsulations. Languages like Cyclone or Cw use the type system to eliminate such errors. Surely Haskell can do something about this? Yes, these techniques are fairly well known now, and hopefully some of the more experienced Haskellers are using them (I certainly use the non-empty list tricks). Any anyone with more than 6 months Haskell knows to avoid fromJust. The problem I see is that head/fromJust errors are usually caused by *beginner* Haskellers, who don't know the techniques for statically avoiding them. One solution would be to deprecate fromJust (we recently decided not to add fromLeft/Right for the same reasons). Having a compiler warning is a good way to encourage good behaviour :) But it seems hardly likely that head will be deprecated any time soon, and we have no support for checked non-empty lists in the base libraries. So how do we help out the beginners, other than warning about fromJust, and providing a useful error message as we can, for when they just go ahead and use head anyway? -- Don ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
RE: [Haskell-cafe] Re: Debugging partial functions by the rules
| The fromJust and `head of empty list' errors are totally equivalent to | the dereferencing of zero pointer in C++ or NullPointerException in | Java. It pains me to see that exactly the same problem arises in | Haskell -- keeping in mind that already in C++ and Java one may | exterminate these errors given right encapsulations. Languages like | Cyclone or Cw use the type system to eliminate such errors. Surely | Haskell can do something about this? | | Yes, these techniques are fairly well known now, and hopefully some of | the more experienced Haskellers are using them (I certainly use the | non-empty list tricks). Any anyone with more than 6 months Haskell knows | to avoid fromJust. | | The problem I see is that head/fromJust errors are usually caused by | *beginner* Haskellers, who don't know the techniques for statically | avoiding them. I don't agree. My programs have invariants that I can't always express in a way that the type system can understand. E.g. I know that a variable is in scope, so searching for it in an environment can't fail: head [ v | (n,v) - env, n==target ] (Maybe if I had an Oleg implant I could express all this in the type system -- but I don't.) But yes, we should have more sophisticated techniques to express and check these invariants. With Dana Xu I'm working on this very thing (see her Haskell Workshop paper http://www.cl.cam.ac.uk/~nx200/research/escH-hw.ps); and Neil Mitchell is doing complementary work at York. So I think there is reason to be hopeful. Simon ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Debugging partial functions by the rules
Hi I have always been wondering why error shouldn't always return a call stack from the occurrance of fromJust up to the function I typed into ghci (or up to main, for that matter). yhi-stack (as yet unreleased) does exactly this, without requiring you to recompile your code even. hat-stack also does this. Thanks Neil ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: Debugging partial functions by the rules
Hi Yes, these techniques are fairly well known now, and hopefully some of the more experienced Haskellers are using them (I certainly use the non-empty list tricks). Any anyone with more than 6 months Haskell knows to avoid fromJust. I'm not, I use fromJust all the time. Ditto for head, init, maximum, foldr1... One solution would be to deprecate fromJust (we recently decided not to add fromLeft/Right for the same reasons). Having a compiler warning is a good way to encourage good behaviour :) We didn't decide not to add fromLeft/fromRight, Russell decided to defer it to a later patch. I am still very interested in them being put in! There seem to be two sides forming to this issue - use partial functions or don't. I don't see why we should restrict the functions available to the partial people, when the unpartial people can choose not to use them. Thanks Neil ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
RE: [Haskell-cafe] Debugging partial functions by the rules
| I have always been wondering why error shouldn't always return a call | stack from the occurrance of fromJust up to the function I typed into | ghci (or up to main, for that matter). | | I guess this is because the call tree is rewritten extensively before | being evaluated, and the output wouldn't be so easy to match to the | source code? But shouldn't the mapping of source tree to executable | tree be bijective, at least in theory? Simon and I have been brainstorming on just such a thing. I've jotted down our current notes (well some of them) here http://hackage.haskell.org/trac/ghc/wiki/ExplicitCallStack Simon ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: Debugging partial functions by the rules
Should Haskell also provide unrestricted side effects, setjmp/ longjmp, missile launching functions, etc? After all, people who don't want to use them can just avoid them. :) On Nov 15, 2006, at 05:07 , Neil Mitchell wrote: Hi Yes, these techniques are fairly well known now, and hopefully some of the more experienced Haskellers are using them (I certainly use the non-empty list tricks). Any anyone with more than 6 months Haskell knows to avoid fromJust. I'm not, I use fromJust all the time. Ditto for head, init, maximum, foldr1... One solution would be to deprecate fromJust (we recently decided not to add fromLeft/Right for the same reasons). Having a compiler warning is a good way to encourage good behaviour :) We didn't decide not to add fromLeft/fromRight, Russell decided to defer it to a later patch. I am still very interested in them being put in! There seem to be two sides forming to this issue - use partial functions or don't. I don't see why we should restrict the functions available to the partial people, when the unpartial people can choose not to use them. Thanks Neil ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: Debugging partial functions by the rules
On Wed, Nov 15, 2006 at 09:04:01AM +, Simon Peyton-Jones wrote: I don't agree. My programs have invariants that I can't always express in a way that the type system can understand. E.g. I know that a variable is in scope, so searching for it in an environment can't fail: head [ v | (n,v) - env, n==target ] (Maybe if I had an Oleg implant I could express all this in the type system -- but I don't.) Yes, that is sometimes true (though many of the uses of fromJust I see could be easily avoided). The problem is an imbalance of costs. It's so easy to write these things, to the point of discouraging alternatives, but the costs come in debugging and reading. Every time I read code containing these functions, I have to perform a non-local analysis to verify the invariant, or even to determine the invariant. I don't think it's unreasonable to ask the programmer to give some justification, in something like (using Neil's library): headNote The variable is in scope [...] That would be extra tagging for the static analysis techniques too. Of course there'd be nothing to stop someone defining head = headNote I'm all right, Jack ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: Debugging partial functions by the rules
Hi Should Haskell also provide unrestricted side effects, setjmp/ longjmp, missile launching functions, etc? After all, people who don't want to use them can just avoid them. :) Fair point. But if you eliminate incomplete cases, and the error function, you'd probably need to increase the power of the type checker by introducing dependant types. It's a good research avenue, and an interesting approach, but its not what Haskell is to me (but it might be to others). Every time I read code containing these functions, I have to perform a non-local analysis to verify the invariant, or even to determine the invariant. If you use the Programmatica annotations, the ESC/Haskell annotations or Catch then you can have these assertions checked for you, and in the case of Catch even infered for you. Admitedly ESC/Haskell and Catch aren't ready for use yet, but they will be soon! Thanks Neil ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: [Haskell] I18N, external strings
Hello Johannes, Wednesday, November 15, 2006, 10:36:10 AM, you wrote: What methods and tools are there for i18n of Haskell programs? In Haskell, I see at least two problems: a) reading the file is in IO if you need utf8 and other encodings support, you can use Streams lib: h - openFile test ReadMode = withEncoding utf8 http://haskell.org/haskellwiki/Library/Streams b) there are no global variables. implicit parameters perhaps? there is a sort of global vars: ref_command = unsafePerformIO$ newIORef$ error undefined ref_command uiStartCommand command = do writeIORef ref_command command .. uiStartProcessing filelist = do command - readIORef ref_command .. but implicit parameters, of course, are more intelligent approach -- Best regards, Bulatmailto:[EMAIL PROTECTED] ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: Debugging partial functions by the rules
Donald Bruce Stewart wrote: So how do we help out the beginners, other than warning about fromJust, and providing a useful error message as we can, for when they just go ahead and use head anyway? Kill head and tail right now and provide a safe equivalent? Either uncons :: [a] - Maybe (a,[a]) which is to be used in conjunction with 'maybe' (or with fmap/first/second/unfoldr) or list :: r - (a - [a] - r) - [a] - r in analogy with 'maybe' and 'either'. Or combine it with 'foldr' to form the paramorphism (if I got the terminology right). Or even better, don't mention the existence of uncons and encourage people to write list consumers in terms of 'destroy'. -Udo -- Sturgeon's Law: Ninety percent of everything is crud. (Sturgeon was an optimist.) signature.asc Description: Digital signature ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re[2]: [Haskell-cafe] Re: Debugging partial functions by the rules
Hello Lennart, Wednesday, November 15, 2006, 3:37:34 PM, you wrote: Should Haskell also provide unrestricted side effects, setjmp/ longjmp, missile launching functions, etc? After all, people who don't want to use them can just avoid them. :) these are documented in tackling the awkward squad, or that remains from our beauty Haskell after uncheckedMissileLauch :) -- Best regards, Bulatmailto:[EMAIL PROTECTED] ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: Haskell custom search engine
By the way, Ihave developped the coreof asearch engine completely in Haskell. It can index arbitrary objects (including files, of course) has definitions for filters, with predefined filters for plain text, HTML/XML and ageneral filter for Haskell data types It has basic search capabilities: it returnsa list ofidentifiers (URIs) of the objects thatcontains all the entered keywords. But it is fairly easy to accept arbitrary AND OR and NOT conditions.Just query parsing is necessary. More info: http://haskell-web.blogspot.com/2006/11/search-engine-written-in-haskell.html The source of Search.hs can be found here ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] the case of the 100-fold program speedup
On Tue, 14 Nov 2006, Seth Gordon wrote: It took me a week to figure out the right algorithm for combining these two procedures and write some almost-working code that implemented it. It took a co-worker of mine another few days to find the bugs that had eluded me. Were these bugs of the kind that would have been found by a static type checker, say the one of Haskell? ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: Debugging partial functions by the rules
Simon Peyton-Jones [EMAIL PROTECTED] writes: | The problem I see is that head/fromJust errors are usually |caused by *beginner* Haskellers, who don't know the |techniques for statically avoiding them. I don't agree. My programs have invariants that I can't always express in a way that the type system can understand. E.g. I know that a variable is in scope, so searching for it in an environment can't fail: head [ v | (n,v) - env, n==target ] (Maybe if I had an Oleg implant I could express all this in the type system -- but I don't.) But instead of “blah (head [ v | (n,v) - env, n==target ]) blah”, you could write blah the_v_in_scope blah where (the_v_in_scope:_) = [ v | (n,v) - env, n==target ] and get a source-code located error message, couldn't you? It's not very high tech, but it's what you would write if head didn't exist, and it doesn't seem /that/ great an imposition. -- Jón Fairbairn [EMAIL PROTECTED] ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: Debugging partial functions by the rules
Hi Haskell is great for equational reasoning. blah the_v_in_scope blah where (the_v_in_scope:_) = [ v | (n,v) - env, n==target ] This piece of code isn't. If you used head then you could trivially inline the_v_in_scope, this way is a lot harder. You might spot a pointfree pattern and lift it up. You might move code around more freely. Lots of patterns like this breaks the equational reasoning in the style that most people are used to. and it doesn't seem /that/ great an imposition. I disagree, this is a massive imposition, and requires lots of refactoring, and is just a little bit ugly. What to go in a where should be the programmers decision, not the decision based on which hoops one has to hop through to write a debuggable Haskell program. Thanks Neil ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: Debugging partial functions by the rules
Lennart Augustsson [EMAIL PROTECTED] writes: Should Haskell also provide unrestricted side effects, setjmp/ longjmp, missile launching functions, etc? After all, people who don't want to use them can just avoid them. :) Yes. It is indeed a common problem that programs have unintended behavior, and partial functions are only the tip of the iceberg. We can keep patching things up. For instance, 'head' can be made to never fail simply by requiring all lists to be infinite. Similarly, fromJust can be fixed by having 'data Maybe a = Just a', and doing away with 'Nothing', which is hardly useful for anything anyway. But this is only superficial patchwork that glosses over the deeper problem. I therefore propose that all functions should either be of type '() - ()', or non-terminating. That should avoid most error messages, I think, and make it very easy to avoid any unintended consequences - and the programmer is relieved of the burden of actively avoiding dangerous stuff. Is it possible to implement this for Haskell'? -k -- If I haven't seen further, it is by standing in the footprints of giants ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: Debugging partial functions by the rules
On Nov 15, 2006, at 9:48 AM, Jón Fairbairn wrote: Simon Peyton-Jones [EMAIL PROTECTED] writes: | The problem I see is that head/fromJust errors are usually |caused by *beginner* Haskellers, who don't know the |techniques for statically avoiding them. I don't agree. My programs have invariants that I can't always express in a way that the type system can understand. E.g. I know that a variable is in scope, so searching for it in an environment can't fail: head [ v | (n,v) - env, n==target ] (Maybe if I had an Oleg implant I could express all this in the type system -- but I don't.) But instead of “blah (head [ v | (n,v) - env, n==target ]) blah”, you could write blah the_v_in_scope blah where (the_v_in_scope:_) = [ v | (n,v) - env, n==target ] and get a source-code located error message, couldn't you? It's not very high tech, but it's what you would write if head didn't exist, and it doesn't seem /that/ great an imposition. Or how about ?? lookupVarible target env = case [ v | (n,v) - env, n==target ] of (x:_) - x _ - assert False $ BUG: Unexpected variable out of scope ++ (show target)++ in environment ++(show env) ... lookupVariable target env It seems to me that every possible use of a partial function has some (possibly imagined) program invariant that prevents it from failing. Otherwise it is downright wrong. 'head', 'fromJust' and friends don't do anything to put that invariant in the program text. Custom functions like the above 1) give you a great opportunity to add a meaningful assertion AND document the program invariant 2) attach some semantic meaning to the operation by naming it 3) make you think about what you're doing and help you avoid writing bugs in the first place 4) give you nice hooks for replacing your data- structure with a better one later, should it be necessary 5) encourage you to break down larger functions into smaller ones. Big win if you ask me. The frequent use of partial functions from the Prelude counters all of these advantages, and I avoid them as much as possible. -- Jón Fairbairn [EMAIL PROTECTED] Rob Dockins Speak softly and drive a Sherman tank. Laugh hard; it's a long way to the bank. -- TMBG ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: Debugging partial functions by the rules
Neil Mitchell [EMAIL PROTECTED] writes: Hi Haskell is great for equational reasoning. blah the_v_in_scope blah where (the_v_in_scope:_) = [ v | (n,v) - env, n==target ] This piece of code isn't. Strange. It's semantically the same, isn't it? Indeed, the definition of head gets you to it. If you used head then you could trivially inline the_v_in_scope, this way is a lot harder. I don't follow that at all. I don't do inlining, the compiler does. Or are you talking about the inlining that was originally there and my version explicitly removed? You might spot a pointfree pattern and lift it up. You might move code around more freely. Lots of patterns like this breaks the equational reasoning in the style that most people are used to. To convince me of that, you'd have to convince me that (head []) doesn't break the equational reasoning. and it doesn't seem /that/ great an imposition. I disagree, this is a massive imposition, and requires lots of refactoring, lots is in the eye of the beholder. You only have to do this where you would have used head -- and if you can already /prove/ that head won't fail, there's no reason to replace it. So it's only necessary in cases where the proof is absent. and is just a little bit ugly. Sure, I don't dispute that. I was merely suggesting that one can already do this for the uncertain cases, rather than have to invoke a whole other set of new machinery just to get a line number in the error message. Your headNote is a good approach, but it strikes me that it's a bit redundant. Instead of “headNote foo” just use “headDef (error foo)”. It's a wee bit longer, but having the “error” out there in the open seems more honest somehow, and there would be fewer function names to remember. -- Jón Fairbairn [EMAIL PROTECTED] ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: Debugging partial functions by the rules
On 11/15/06, Donald Bruce Stewart [EMAIL PROTECTED] wrote: Yes, these techniques are fairly well known now, and hopefully some ofthe more experienced Haskellers are using them (I certainly use thenon-empty list tricks). Any anyone with more than 6 months Haskell knows to avoid fromJust.The problem I see is that head/fromJust errors are usually caused by*beginner* Haskellers, who don't know the techniques for staticallyavoiding them.I'm one of those beginning Haskellers (about one month in) and I'd like to know these techniques. Are they written up anywhere? Justinp.s. apologies for the double-email Donald - forget to CC the list on the first one. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Haskell Debugging
On Mon, Nov 13, 2006 at 04:32:34PM +0100, Valentin Gjorgjioski wrote: import Hugs.Observe ex8 :: [Float] ex8 = (observe after reverse ) reverse [10.0,7.0,3.0,0.0,4.0] gives me ex8 [4.0,0.0,3.0,7.0,10.0] Observations after reverse { \ ($-990871 : $-990888 : $-990905 : $-990922 : $-990939 : []) - $-990939 : $-990922 : $-990905 : $-990888 : $-990871 : [] } It's a Hugs bug (Float only, Double is fine). Now fixed in CVS. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: Debugging partial functions by the rules
Robert Dockins [EMAIL PROTECTED] writes: On Nov 15, 2006, at 9:48 AM, Jón Fairbairn wrote: But instead of “blah (head [ v | (n,v) - env, n==target ]) blah”, you could write blah the_v_in_scope blah where (the_v_in_scope:_) = [ v | (n,v) - env, n==target ] Or how about ?? lookupVarible target env = case [ v | (n,v) - env, n==target ] of (x:_) - x _ - assert False $ BUG: Unexpected variable out of scope ++ (show target)++ in environment ++(show env) ... lookupVariable target env It seems to me that every possible use of a partial function has some (possibly imagined) program invariant that prevents it from failing. Otherwise it is downright wrong. 'head', 'fromJust' and friends don't do anything to put that invariant in the program text. Hear hear. -- Jón Fairbairn [EMAIL PROTECTED] ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Haskell Debugging
On 15.11.2006 17:38 Ross Paterson wrote: On Mon, Nov 13, 2006 at 04:32:34PM +0100, Valentin Gjorgjioski wrote: import Hugs.Observe ex8 :: [Float] ex8 = (observe after reverse ) reverse [10.0,7.0,3.0,0.0,4.0] gives me ex8 [4.0,0.0,3.0,7.0,10.0] Observations after reverse { \ ($-990871 : $-990888 : $-990905 : $-990922 : $-990939 : []) - $-990939 : $-990922 : $-990905 : $-990888 : $-990871 : [] } It's a Hugs bug (Float only, Double is fine). Now fixed in CVS. Oh, thanks a lot. Nice to hear good news. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe -- Valentin Gjorgjioski Bachelor of Computer Science Department of Knowledge Technologies, Jozef Stefan Institute Jamova 39, SI-1000 Ljubljana, Slovenia Phone: +386 1 477 3343 Fax:+386 1 477 3315 Web:http://kt.ijs.si/ValentinGjorgjioski/ Email: [EMAIL PROTECTED] ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: Debugging partial functions by the rules
Robert Dockins wrote: Or how about ?? lookupVarible target env = case [ v | (n,v) - env, n==target ] of (x:_) - x _ - assert False $ BUG: Unexpected variable out of scope ++(show target)++ in environment ++(show env) Other have pointed out that, in the CURRENT Haskell semantics, the above is quite difficult to reason about. Note that the whole point of Wolfram Kahl's Pattern Matching Calculus is to restore equational reasoning to pattern-matches. http://www.cas.mcmaster.ca/~kahl/PMC/ Jacques ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] the case of the 100-fold program speedup
As Lily Tomlin would say, neVERmind. Simon P-J asked me, in email, whether the deforestation was the thing that actually made the program faster or whether it was just the thing that made me think about how to solve the problem. I realized that my fast program had *another* difference from the earlier, slower program: it was based on an algorithm that was specifically designed to clip polygons to rectangles, whereas OGR just had a function to compute the intersection between two arbitrary polygons. So I threw together a version that accumulated all the vertices of the clipped polygon in a list and then iterated through the list to compute the centroid--i.e., preserving everything from my fast program except the deforestation--and it ran at almost exactly the same speed as the deforested program. (Actually, it ran 2% faster, but that could be just random variation from things like the load on the database server.) The tragedy of science: a beautiful theory slain by an ugly fact. T. H. Huxley said it first. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: Debugging partial functions by the rules
From: Robert Dockins [EMAIL PROTECTED] It seems to me that every possible use of a partial function has some (possibly imagined) program invariant that prevents it from failing. Otherwise it is downright wrong. 'head', 'fromJust' and friends don't do anything to put that invariant in the program text. Well, not really. For example, I often write programs with command line arguments, that contain code of the form do ... [a,b] - getArgs ... Of course the pattern match is partial, but if itfails, then the standard error message is good enough. This applies to "throw away" code, of course, and if I decide to keep the code then I sooner or later extend it to fix the partiality and give a more sensible error message.But it's still an advantage to beABLE to write the more concise, but cruder version initially. This isn't a trivial point. We know that error handling codeis a majorpart ofsoftware cost--it can even dominate the cost of the "correct case" code (by a large factor).Erlang's "program for the correct case" strategy, coupled with good fault tolerance mechanisms, is one reason for its commercial success--the cost of including error handling code *everywhere* is avoided. Butthis means accepting that code *may*very well fail--the failure is just going to be handled somewhere else. Haskell (or at least GHC)has good exception handling mechanisms too. We should be prepared to use them, and "let it fail" when thingsgo wrong. The savings of doing so are too large to ignore. John ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] type keeping rounding, typeable (and a difficulty)
Hi, I've been trying to compile the following function (rounding to a desired degree): roundDec :: (Num a, Typeable a) = Int - a - a roundDec d a = let t = show (typeOf a) in case t of Double - roundDDec d a Complex Double - roundCDec d a otherwise - a -- or something The two other functions are roundCDec :: (RealFloat a) = Int - Complex a - Complex a roundCDec d (c :+ b) = (roundDDec d c :+ roundDDec d b) and roundDDec :: (RealFloat a) = Int - a - a roundDDec d a = a -- or somegthing Compiler gives the following error message: Couldn't match expected type `Complex a' against inferred type `a1' (a rigid variable) `a1' is bound by the type signature for `roundDec' at FFT.hs:57:17 In the second argument of `roundCDec', namely `a' In the expression: roundCDec d a In a case alternative: Complex Double - roundCDec d a If in the roundDDec a's are replaced with Double, there will be similar error message from the Double-line. The functionality can be written differently, but I wanted to try write rounding having in a signature at least (Num a) = Int - a - a. Again, any help would be appreciated a lot! Thanks in advance! br, Isto ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] type keeping rounding, typeable (and a difficulty)
isto wrote: ] I've been trying to compile the following function ] (rounding to a desired degree): ] ] roundDec :: (Num a, Typeable a) = Int - a - a ] roundDec d a = ] let t = show (typeOf a) ] in case t of ] Double - roundDDec d a ] Complex Double - roundCDec d a ] otherwise - a -- or something ] ] The two other functions are ] ] roundCDec :: (RealFloat a) = Int - Complex a - Complex a ] roundCDec d (c :+ b) = (roundDDec d c :+ roundDDec d b) ] and ] roundDDec :: (RealFloat a) = Int - a - a ] roundDDec d a = a -- or somegthing Maybe you want type classes instead? import Complex class Round a where roundD :: Int - a - a instance Round Double where roundD d a = a instance (Round a, RealFloat a) = Round (Complex a) where roundD d (c :+ b) = (roundD d c :+ roundD d b) ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: Re: Debugging partial functions by the rules
John Hughes wrote: From: Robert Dockins [EMAIL PROTECTED] It seems to me that every possible use of a partial function has some (possibly imagined) program invariant that prevents it from failing. Otherwise it is downright wrong. 'head', 'fromJust' and friends don't do anything to put that invariant in the program text. Well, not really. For example, I often write programs with command line arguments, that contain code of the form do ... [a,b] - getArgs ... Of course the pattern match is partial, but if it fails, then the standard error message is good enough. This applies to throw away code, of course, and if I decide to keep the code then I sooner or later extend it to fix the partiality and give a more sensible error message. But it's still an advantage to be ABLE to write the more concise, but cruder version initially. This isn't a trivial point. We know that error handling code is a major part of software cost--it can even dominate the cost of the correct case code (by a large factor). Erlang's program for the correct case strategy, coupled with good fault tolerance mechanisms, is one reason for its commercial success--the cost of including error handling code *everywhere* is avoided. But this means accepting that code *may* very well fail--the failure is just going to be handled somewhere else. Haskell (or at least GHC) has good exception handling mechanisms too. We should be prepared to use them, and let it fail when things go wrong. The savings of doing so are too large to ignore. But note that Erlang will give you a stack trace for unhandled exceptions which Haskell (currently?) doesn't/can't. Also, I remember an Erlang expert (Ulf Wiger?) stating recently that 'catching and re-throwing expections in most cases tends to hide program errors rather than avoid them' (quoted non-verbatim from memory, I can't recall the name of the paper). Lastly, Erlang's program for the correct case is not meant for things like input of data from sources outside the program's control, but only applies to not-checking for program internal invariants. I would be very surprised if there were Erlang experts encouraging throwaway code such as your example above. Cheers, Ben ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: Debugging partial functions by the rules
On Wednesday 15 November 2006 15:53, John Hughes wrote: From: Robert Dockins [EMAIL PROTECTED] It seems to me that every possible use of a partial function has some (possibly imagined) program invariant that prevents it from failing. Otherwise it is downright wrong. 'head', 'fromJust' and friends don't do anything to put that invariant in the program text. Well, not really. For example, I often write programs with command line arguments, that contain code of the form do ... [a,b] - getArgs ... Of course the pattern match is partial, but if it fails, then the standard error message is good enough. I'd actually put this in a different category than 'partial function' (in what might be regarded as an abuse of termonology). This is failure in a monad, and is something I personally use a lot. Failure in IO just usually happens to have behavior very similar to calling 'error'. I'll often write code in an arbitrary monad just to model partiality via the 'fail' function. Sometimes, as here, I use partial pattern matches to do this implicitly. Why is this better than 'error'? Because it allows the code consumer decide how to deal with problems. You can use runIdentity to convert 'fail' to 'error'. You can run with runErrorT and recover the error message. You can run it in a custom moand that has some other fancy error handling. etc, etc. This applies to throw away code, of course, and if I decide to keep the code then I sooner or later extend it to fix the partiality and give a more sensible error message. But it's still an advantage to be ABLE to write the more concise, but cruder version initially. I'm not against partial pattern matching. I think it's way better than using partial projection functions. This isn't a trivial point. We know that error handling code is a major part of software cost--it can even dominate the cost of the correct case code (by a large factor). Erlang's program for the correct case strategy, coupled with good fault tolerance mechanisms, is one reason for its commercial success--the cost of including error handling code *everywhere* is avoided. But this means accepting that code *may* very well fail--the failure is just going to be handled somewhere else. Haskell (or at least GHC) has good exception handling mechanisms too. We should be prepared to use them, and let it fail when things go wrong. The savings of doing so are too large to ignore. John -- Rob Dockins Talk softly and drive a Sherman tank. Laugh hard, it's a long way to the bank. -- TMBG ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] submenu doesn't seem to work properly in wxhaskell
Hi, Let's transfer this to wxhaskell-users. I've attached your example as a small .lhs file and makefile. For Debian Linux, uncomment the -lwx_gtk2u_gl-2.6 line or otherwise, modify to taste. The following code doesn't seem to work properly. Either the main entry (m1/mp1) or it's sub menu entry (ms1/mps1) do not seem to propagate the event when pressed. It is possible to make it working by uncomments the lines where the menu commands are registered in the frame. It seems to work fine on my Mac at least, unless I'm misunderstanding something. Selecting the menubar items m1 and ms1 both putStr their respective strings, as do mp1 and mps1 (right click on the main frame). On the other hand, under Linux, m1 does not putStr, whereas the others do. Is this the problem you are experiencing? -- Eric Kow http://www.loria.fr/~kow PGP Key ID: 08AC04F9 Merci de corriger mon français. pgpXSpqpru5In.pgp Description: PGP signature ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: Debugging partial functions by the rules
On Nov 15, 2006, at 3:21 AM, [EMAIL PROTECTED] wrote: Donald Bruce Stewart wrote: So all this talk of locating head [] and fromJust failures got me thinking: Couldn't we just use rewrite rules to rewrite *transparently* all uses of fromJust to safeFromJust, tagging the call site with a location? I'm sorry for shifting the topic: I'm wondering if, rather than trying to make an error message more informative, we ought to make sure that no error will ever arise? ... This topic has been discussed at length on this list. It seems that the discussion came to the conclusion that eliminating head of the empty list error is possible and quite easy in Haskell. http://www.haskell.org/pipermail/haskell-cafe/2006-September/ 017915.html But this code contains a function with_non_empty_list (or perhaps with_nonempty_list or withNonemptyList or...) which has the same confusing failure mode as the examples under discussion. Fundamentally, if we try to package up check for failure in a function, whether the function does something useful as well (head, tail, fromJust) or not (withNonemptyList), we miss out on useful contextual information when our program fails. In addition, we have this rather nice assembly of functions which work on ordinary lists. Sadly, rewriting them all to also work on NonEmptyList or MySpecialInvariantList is a nontrivial task. Which isn't to say that I disapprove of this style: check your invariants early, maintain them as you go. I'm quite enjoying the escH paper, but I get through about a column per day between compiles. :-) -Jan-Willem Maessen smime.p7s Description: S/MIME cryptographic signature ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] submenu doesn't seem to work properly in wxhaskell
On Wed, Nov 15, 2006 at 23:10:44 +0100, Eric Y. Kow wrote: I've attached your example as a small .lhs file and makefile. For Debian Linux, uncomment the -lwx_gtk2u_gl-2.6 line or otherwise, modify to taste. Here are the files, really attached this time. -- Eric Kow http://www.loria.fr/~kow PGP Key ID: 08AC04F9 Merci de corriger mon français. Dear all, The following code doesn't seem to work properly. Either the main entry (m1/mp1) or it's sub menu entry (ms1/mps1) do not seem to propagate the event when pressed. It is possible to make it working by uncomments the lines where the menu commands are registered in the frame. I have the following two questions: 1. Why doesn't the plain code work. Am I missing something or doing something wrong? 2. Doesn't registering eventhandlers in the frame introduce a memory/resource leak, especially in the case of popups? Any suggestions or comments appreciated. Thanks. Kind regards, Maarten module Main where import Graphics.UI.WX main :: IO () main = start gui gui :: IO () gui = do f - frame [ text := Hello world! ] m - menuPane [ text := Menu ] m1 - menuItem m [ text := Menu m1 , on command := putStrLn menu m1] -- set f [ on (menu m1) := putStrLn menu m1 ] menuLine m sub - menuPane [text := Sub menu] ms1 - menuItem sub [ text := submenu ms1 , on command := putStrLn submenu ms1 ] -- set f [ on (menu ms1) := putStrLn submenu ms1 ] menuSub m sub [ text := Sub ] menuItem m [text := Exit, on command := close f] set f [menuBar := [m], on mouse := mouseEvent f, clientSize := sz 200 200 ] return () mouseEvent f eventMouse = do case eventMouse of MouseRightDown mousePoint _ - doPopup f mousePoint _ - return () doPopup f mousePoint = do m - makePopupMenu f Popup Doesnt' work... menuPopup m mousePoint f objectDelete m makePopupMenu f c t = do mp - menuPane [ text := c ] mp1 - menuItem mp [ text := Popup mp1 , on command := putStrLn popup mp1] -- set f [ on (menu mp1) := putStrLn popup mp1 ] menuLine mp sub - menuPane [text := more text] mps1 - menuItem sub [ text := Popup mps1 , on command := putStrLn popup mps1] menuSub mp sub [ text := Sub ] -- set f [ on (menu mps1) := putStrLn popup mps1 ] return mp COMPILE=ghc -package wx #COMPILE+=-lwx_gtk2u_gl-2.6 ifeq ($(shell uname),Darwin) PREP=macosx-app else PREP=\# endif APPS= MenuProblems\ .PHONY: clean all: $(APPS) %: %.lhs $(COMPILE) -o $@ $ $(PREP) $@ clean: rm -rf $(APPS) *.o *.hi *.app pgpEw1kdUHxM2.pgp Description: PGP signature ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] forall and a parse error
Probably unrelated, but this thread is what triggered it for me. There is a minor bug in showing impredicative types without -fglasgow-exts: *hope I got that right* Prelude let x = [] :: [forall a. a] interactive:1:23: Warning: Accepting non-standard infix type constructor `.' Use -fglasgow-exts to avoid this warning Prelude :t x x :: [. (forall a) a] When -fglasgow-exts is set it shows what it should: Prelude :t x x :: [forall a. a] Groetjes, Remi On Tue, Jul 04, 2006 at 04:55:49PM +0100, Simon Peyton-Jones wrote: It's a parsing infelicity. (Inside square brackets the parser knows not to expect a forall, whereas inside round parens it might.) Perhaps it should be more accepting in square brackets, and reject later. Which the current HEAD does -- actually [forall a. a-a] is ok in the HEAD, see our ICFP06 paper. Simon | -Original Message- | From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] On Behalf Of Neil | Mitchell | Sent: 03 July 2006 19:44 | To: Haskell Cafe | Subject: [Haskell-cafe] forall and a parse error | | Hi, | | I was experimenting with forall and higher rank types briefly, in particular: | | x :: [forall a . a] | | This is illegal because of: | http://www.haskell.org/ghc/docs/latest/html/users_guide/type-extensions. html#universal-quantification | | Which is fine, however its surprising to compare the error messages: | | [forall a . a] | parse error on input `forall' | | [(forall a . a)] | Illegal polymorphic or qualified type: forall a. a | In the type signature: lst :: [(forall a. a)] | | In normal Haskell, I tend to view [x] as equivalent to [(x)] (provided | that x is not a tuple) but in this case it has a different meaning - | albeit both are erronous meanings. | | When running the example with Hugs, they both come out as syntax | errors - the first on the forall, the second on the closing square | bracket. | | Thanks | | Neil | ___ | Haskell-Cafe mailing list | Haskell-Cafe@haskell.org | http://www.haskell.org/mailman/listinfo/haskell-cafe ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: Debugging partial functions by the rules
This isn't a trivial point. We know that error handling code is a major part of software cost--it can even dominate the cost of the correct case code (by a large factor). Erlang's program for the correct case strategy, coupled with good fault tolerance mechanisms, is one reason for its commercial success--the cost of including error handling code *everywhere* is avoided. But this means accepting that code *may* very well fail--the failure is just going to be handled somewhere else. I've been waiting for someone to put in a quick word for Erlang's approach;-) if I recall correctly, the opposite to programming for the correct case was to program defensively - try to predict and handle all errors where they occur, and the arguments against that style were that: 1 it spreads error handling all over the place, obscuring the correct case, instead of factoring out the handling code into a coherent framework 2 it tries to handle errors where there is nothing to be done about them, leading to potentially dangerous default values, or catch/rethrow, or even sweaping helpful diagnostics under the carpet. As I've been trying to argue, the Haskell language report forces implementations to handle functions with non-exhaustive left-hand sides defensively: - the left-hand sides are translated into a case on the right-hand side - the case is completed by a default branch calling error since this behaviour is implicit, there is little that the programmer can do about it, and unlike inlined partial matches (such as your getArgs example), this forces the error to be raised where the offending context is no longer available. it is perhaps a small thing, and mostly concerns everyone just once (because once bitten, we try to untrain ourselves and our co-workers from using those easy functions like head or tail, fromJust, etc.), but perhaps Haskell' should fix this? Instead of forcing implementations to let non-exhaustive functions accept responsibility for arguments they are not equipped to handle, such arguments should be rejected at the call site, with more useful error context. Haskell (or at least GHC) has good exception handling mechanisms too. We should be prepared to use them, and let it fail when things go wrong. The savings of doing so are too large to ignore. indeed, though lazyness makes these things a little more cumbersome. let it fail really means don't worry about it here, but have a safety net separate from the main act - lazyness might keep our failing trapeze artists in mid flight until someone chooses to observe them, possible forcing them to complete their crash after the safety net has been removed.. Claus -- Data.Ransom: API documentation withheld pending initial payment ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Debugging partial functions by the rules
Couldn't we just use rewrite rules to rewrite *transparently* all uses of fromJust to safeFromJust, tagging the call site with a location? .. Looks good! But that is deceiving: the assert was expanded before the rule fired, and refers to the rewrite rule source line (line 19), not the fromJust call site (line 12). Now if we could just have the 'assert' token inserted into the AST before it was expanded, we'd be home and dry. Could this be done with TH? Or could we arrange for asserts in rewrite rules not to be expanded till later? .. Any ideas? http://www.haskell.org/pipermail/glasgow-haskell-users/2006-November/011545.html claus ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] RE: Debugging partial functions by the rules
| Looks good! But that is deceiving: the assert was expanded before the rule | fired, and refers to the rewrite rule source line (line 19), not the fromJust | call site (line 12). Now if we could just have the 'assert' token inserted | into the AST before it was expanded, we'd be home and dry. Could this be done | with TH? Or could we arrange for asserts in rewrite rules not to be expanded | till later? That's difficult. Trouble is, the assert expansion happens right at the front, before any desugaring or program transformation. But rewrite rules fire much, much later, in the simplifier. It is, however, possible (or could be made possible) to answer the question When this rule fires, what module am I compiling, and make that available in the RHS of the rule, by some magic incantation. Harder would be when this rule fires, what top-level function's RHS is being simplified?. But even that is tricky, because it might be lvl_4532, a function created by the simplifier itself. The only solid way to connect to programmer-comprehensible stuff is by transforming the original, unadulterated source code, as Hat does, and as Jhc does, and as Simon and I are musing about doing. Your idea is to do something cheap and cheerful, which is always a good plan. But I don't see how to make it fly. (The -O thing, and/or providing $currentLocation rather than just 'assert', seem easier.) Simon ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] help with threadDelay
Hi, I'm using GHC 6.6 (debian/etch) - and having some fun with threadDelay. When compiled without the -threaded compiler argument it behaves as documented - waits at least the interval - for example: Tgt/Actual = 0.00/0.036174s, diff = 0.036174s Tgt/Actual = 0.01/0.049385s, diff = 0.049384s Tgt/Actual = 0.05/0.049492s, diff = 0.049487s Tgt/Actual = 0.25/0.049596s, diff = 0.049571s Tgt/Actual = 0.000125/0.049655s, diff = 0.04953s Tgt/Actual = 0.000625/0.04969s, diff = 0.049065s Tgt/Actual = 0.003125/0.049684s, diff = 0.046559s Tgt/Actual = 0.015625/0.04962s, diff = 0.033995s Tgt/Actual = 0.078125/0.099668s, diff = 0.021543s Tgt/Actual = 0.390625/0.399637s, diff = 0.009012s Tgt/Actual = 1.953125/1.999515s, diff = 0.04639s Tgt/Actual = 9.765625/9.799505s, diff = 0.03388s however when -threaded is used you get some interesting effects, including returning too early: Tgt/Actual = 0.00/0.93s, diff = 0.93s Tgt/Actual = 0.01/0.31s, diff = 0.3s Tgt/Actual = 0.05/0.29s, diff = 0.24s Tgt/Actual = 0.25/0.28s, diff = 0.03s Tgt/Actual = 0.000125/0.34s, diff = -0.91s Tgt/Actual = 0.000625/0.35s, diff = -0.00059s Tgt/Actual = 0.003125/0.29s, diff = -0.003096s Tgt/Actual = 0.015625/0.28s, diff = -0.015597s Tgt/Actual = 0.078125/0.058525s, diff = -0.0196s Tgt/Actual = 0.390625/0.389669s, diff = -0.000956s Tgt/Actual = 1.953125/1.939513s, diff = -0.013612s Tgt/Actual = 9.765625/9.749573s, diff = -0.016052s The program I used to generate this is :- import Control.Concurrent import Data.Time import Text.Printf main = mapM_ delay (0 : take 11 (iterate (*5) 1)) delay n = do tS - getCurrentTime threadDelay n tE - getCurrentTime let n' = toRational n / 10^6 n'' = fromRational (n') :: Double obs = diffUTCTime tE tS printf Tgt/Actual = %0.6f/%s, diff = %s\n n'' (show obs) (show $ obs - fromRational n') return () Any suggestions? Neil ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: Debugging partial functions by the rules
It must be stressed that the advocated technique for avoiding partial function errors requires *NO* research advances, *NO* dependent types, *NO* annotations, and *NO* tools. Everything is possible in Haskell as it is -- actually, even in Haskell98. As a matter of fact, exactly the same approach applies to OCaml (and even to any language with a half-decent type system, including Java and C++). The only required advancement is in our thinking and programming style. First, regarding fromJust: to quote Nancy Reagan, let's `Just say NO'. Let us assume that `fromJust' just does not exist. That does not reduce any expressiveness, as `maybe' always suffices. The latter function causes us to think of the boundary case, when the value is Nothing. And if we are absolutely positive that the value is (Just x), we can always write maybe (assert False undefined) id v This is *exactly* equivalent to `fromJust v', only with a better error message. So, no `safeFromJust' is ever necessary! The expression above takes longer to type than `fromJust v' -- and I consider that a feature. Whenever I am telling the compiler that I know better, I'd rather had to type it in more words -- so I could think meanwhile if I indeed know better. Also, such phrases should stand out in the code. I'd be quite happy seeing fromJust removed from the standard libraries, or at least tagged `deprecated' or with the stigma attached that is rightfully accorded to unsafePerformIO. Regarding head and tail. Here's the 0th approximation of the advocated approach: {-# Haskell98! #-} -- Safe list functions module NList (FullList, fromFL, indeedFL, decon, head, tail, Listable (..) ) where import Prelude hiding (head, tail) newtype FullList a = FullList [a] -- data constructor is not exported! fromFL (FullList x) = x -- Injection into general lists -- The following is an analogue of `maybe' indeedFL :: [a] - w - (FullList a - w) - w indeedFL x on_empty on_full | null x = on_empty | otherwise = on_full $ FullList x -- A possible alternative, with an extra Maybe tagging -- indeedFL :: [a] - Maybe (FullList a) -- A more direct analogue of `maybe', for lists decon :: [a] - w - (a - [a] - w) - w decon []on_empty on_full = on_empty decon (h:t) on_empty on_full = on_full h t -- The following are _total_ functions -- They are guaranteed to be safe, and so we could have used -- unsafeHead# and unsafeTail# if GHC provides though... head :: FullList a - a head (FullList (x:_)) = x tail :: FullList a - [a] tail (FullList (_:x)) = x -- Mapping over a non-empty list gives a non-empty list instance Functor FullList where fmap f (FullList x) = FullList $ map f x -- Adding something to a general list surely gives a non-empty list infixr 5 !: class Listable l where (!:) :: a - l a - FullList a instance Listable [] where (!:) h t = FullList (h:t) instance Listable FullList where (!:) h (FullList t) = FullList (h:t) Now we can write import NList import Prelude hiding (head, tail) safe_reverse l = loop l [] where loop l accum = indeedFL l accum $ (\l - loop (tail l) (head l : accum)) test1 = safe_reverse [1,2,3] As we can see, the null test is algorithmic. After we've done it, head and tail no longer need to check for null list. Those head and tail functions are total. Thus we achieve both safety and performance. We can also write -- Again, we are statically assured of no head [] error! test2 = head $ 1 !: 2 !: 3 !: [] This would look better had `[1,2,3]' been a rebindable syntax similar to `do'. I should point to http://pobox.com/~oleg/ftp/Computation/lightweight-dependent-typing.html for further, more complex examples. We can also use the approach to ensure various control properties, e.g., the yield property: a thread may not invoke `yield' while holding a lock. We can assure this property both for recursive and non-recursive locks. If there is a surprise in this, it is in the triviality of approach. One can't help but wonder why don't we program in this style. Simon Peyton-Jones wrote: My programs have invariants that I can't always express in a way that the type system can understand. E.g. I know that a variable is in scope, so searching for it in an environment can't fail: head [ v | (n,v) - env, n==target ] In the 0th approximation, the above line will read as indeedFL [ v | (n,v) - env, n==target ] (assert False undefined) head Alternatively, one may write case [ v | (n,v) - env, n==target ] of (h:_) - h with the compiler issuing a warning over the incomplete match and prompting us to consider the empty list case (writing assert False undefined if we are sure it can't happen). I have a hunch we can do better and really express our knowledge that [ v | (n,v) - env,
[Haskell-cafe] Newbie; Can't Install Hat From Source
Hi all, I have been trying to install Hat for the last couple of days but GHC does not recognize it as a package. I compiled 2.05 from source, but at the 'make install' step I see this error message: **Begin Output** ./configure --install Configuring for hat... [ 2.05 ] Starting with earlier config in targets/ix86-Linux/config.cache [ config: ix86-Linux/ by [EMAIL PROTECTED] on 15 Nov 2006 ] (but cmdline options have precedence) Looking for already-installed Haskell compilers: Looking for ghc... found 6.6 Looking for nhc98... (not found) Looking for hmake... found 3.13 You said you want to use ghc to build hat. Done. Configuration report for hat. You are going to build hat with:ghc Executables need .exe suffix? no (detected) Testing for the glib library: no (using slower replacement) Installation directories are now created/checked. Install directory root is: /usr/local Hat interface files (.hx) go into: /usr/local/include/hat-2.05 (exists) Array.hx .. Debug/Trace.hx Installing hat as a ghc package: Installing hat package for ghc under /usr/local/lib/hat-2.05/ix86-Linux/ghc-606 ghc-pkg: cannot find package hat -ERROR MESSAGE! Reading package info from stdin ... done. ghc-pkg: package hat-2.4 is already installed Scripts go into: /usr/local/bin (exists) hat-graph hat-trans hat-tools: hat-stack hat-check hat-observe hat-detect hat-delta hat-view hat-trail hat-anim hat-explore hat-cover black-hat hat-nonterm pretty-hat Executables go into: /usr/local/lib/hat-2.05/ix86-Linux (exists) config hat-anim hat-check hat-cover hat-delta hat-detect hat-explore hat-nonterm hat-observe hat-stack hat-trail hat-trans hat-view black-hat pretty-hat Man pages go into: /usr/local/man/man1 (exists) hat-anim.1 hat-delta.1 hat-detect.1 hat-observe.1 hat-stack.1 hat-trail.1 hat-trans.1 pretty-hat.1 Not (re-)installing html documents Saving current configuration in targets/ix86-Linux/config.cache Done. Please ensure /usr/local/bin is in your PATH variable. **End Of Output** The output of 'ghc-pkg list' is: /usr/local/lib/ghc-6.6/package.conf: Cabal-1.1.6, HUnit-1.1, QuickCheck-1.0, base-2.0, cgi-2006.9.6, fgl-5.2, (ghc-6.6), haskell-src-1.0, haskell98-1.0, html-1.0, mtl-1.0, network-2.0, parsec-2.0, readline-1.0, regex-base-0.71, regex-compat-0.71, regex-posix-0.71, rts-1.0, stm-2.0, template-haskell-2.0, time-1.0, unix-1.0, xhtml-2006.9.13 /home/deech/.ghc/i386-linux-6.6/package.conf: (hat-2.4) ERROR!!! For some reason it thinks that hat-2.4 is installed. I tried to run a test program saved in HatTest.hs: import Prelude main = do { print Hello; } When I compile it with 'hmake -hat HatTest' I get the following error: hat-trans HatTest.hs Wrote Hat/HatTest.hs ghc-6.6 -c -package hat -o Hat/HatTest.o Hat/HatTest.hs Hat/HatTest.hs:3:0: Bad interface file: /usr/local/imports/hat-2.05/ghc-606/Hat/PreludeBasic.hi Something is amiss; requested module hat-2.4:Hat.PreludeBasic differs from name found in the interface file hat:Hat.PreludeBasic I'm not really sure how to proceed. Any help is appreciated. BTW I get the ghc-package: cannot find package hat when I 'apt-get install' it too. Thanks.. Deech _ View Athletes Collections with Live Search http://sportmaps.live.com/index.html?source=hmemailtaglinenov06FORM=MGAC01 ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: Debugging partial functions by the rules
Jan-Willem Maessen wrote: In addition, we have this rather nice assembly of functions which work on ordinary lists. Sadly, rewriting them all to also work on NonEmptyList or MySpecialInvariantList is a nontrivial task. That's an excellent question. Indeed, let us assume we have a function foo:: [a] - [a] (whose code, if available, we'd rather not change) and we want to write something like \l - [head l, head (foo l)] To use the safe `head' from NList.hs , we should write \l - indeedFL l onempty (\l - [head l, head (foo l)]) But that doesn't type: first of all, foo applies to [a] rather than FullList a, and second, the result of foo is not FullList a, required by our |head|. The first problem is easy to solve: we can always inject FullList a into the general list: fromFL. We insist on writing the latter function explicitly, which keeps the typesystem simple, free of subtyping and implicit coercions. One may regard fromFL as an analogue of fromIntegral -- which, too, we have to write explicitly, in any code with more than one sort of integral numbers (e.g., Int and Integer, or Int and CInt). If we are not sure if our function foo maps non-empty lists to non-empty lists, we really should handle the empty list case: \l - indeedFL l onempty $ \l - [head l, indeedFL (foo $ fromFL l) onempty' head] If we have a hunch that foo maps non-empty lists to non-empty lists, but we are too busy to verify it, we can write \l - indeedFL l onempty $ \l - [head l, indeedFL (foo $ fromFL l) (assert (const False msg) undefined) head] where msg = I'm quite sure foo maps non-empty lists to ++ non-empty lists. I'll be darned if it doesn't. That would get the code running. Possibly at some future date (during the code review?) I'll be called to justify my hunch, to whatever degree of formality (informal argument, formal proof) required by the policies in effect. If I fail at this justification, I'd better think what to do if the result of foo is really the empty list. If I succeed, I'd be given permission to update the module NList with the following definition nfoo (FullList x) = FullList $ foo x after which I could write \l - indeedFL l onempty (\l - [head l, head (nfoo l)]) with no extra empty list checks. It goes without saying that it would save a lot of typing if List were a typeclass (like Num) rather than a datatype... ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe