Currying and errors

I just found myself writing a function that looked like this:
isSubsumedByWith :: TBox c -> c -> c -> Bool isSubsumedByWith [] c d = isALSubsumedBy c d isSubsumedByWith _ _ _ = error "TBox reasoning not supported for AL"
and immediately noticed that I might also write this:
isSubsumedByWith :: TBox c -> c -> c -> Bool isSubsumedByWith [] = isALSubsumedBy isSubsumedByWith _ = error "TBox reasoning not supported for AL"
which led me to thinking about the difference between these two functions (I reason there must be a difference, because the call of 'error' is required to fulfil (terminology?) values of different types). I think it is this: Suppose I evaluate an expression: let s = isSubsumedByWith [foo] in seq s e then I think the first case will return a legitimate function, albeit one that returns error when it is applied, and the second will cause an error to be returned immediately. Am I right? Is this all? #g ------------ Graham Klyne For email: http://www.ninebynine.org/#Contact

Graham Klyne
isSubsumedByWith :: TBox c -> c -> c -> Bool isSubsumedByWith [] c d = isALSubsumedBy c d isSubsumedByWith _ _ _ = error "TBox reasoning not supported for AL"
and immediately noticed that I might also write this:
isSubsumedByWith :: TBox c -> c -> c -> Bool isSubsumedByWith [] = isALSubsumedBy isSubsumedByWith _ = error "TBox reasoning not supported for AL"
A difference is that you can generally assume that: let x = isSubsumedByWith [] 0 in x 0 && x 1 will evaluate 'isALSubsumedBy 0' only once, so if it has some work to do before waiting for the second argument, the work will be shared for both arguments. They will give the same result anyway, but may need different amounts of work to do. OTOH if isALSubsumedBy does not have any shared the work to do, but is itself defined with two arguments, then applying it to both arguments at once is more efficient (has less overhead). Manually lifting a partial application is valuable only when we expect that it shares some real work. An optimizing compiler can change the effect it in either direction. The above is not a formal guarantee, only some expectation which might be useful for tuning performance.
I think it is this: Suppose I evaluate an expression:
let s = isSubsumedByWith [foo] in seq s e
then I think the first case will return a legitimate function, albeit one that returns error when it is applied, and the second will cause an error to be returned immediately. Am I right?
Yes. And this time an optimizing compiler can't exchange that. While program termination is a part of the language semantics, the amount of recomputation and sharing is not formally specified, and you can at most hope that the compiler would do no worse than the obvious naive implementation would do (i.e. that its optimizations will not become pessimizations). -- __("< Marcin Kowalczyk \__/ qrczak@knm.org.pl ^^ http://qrnik.knm.org.pl/~qrczak/

On Mon, Nov 08, 2004 at 02:20:45PM +0000, Graham Klyne wrote:
I just found myself writing a function that looked like this:
isSubsumedByWith :: TBox c -> c -> c -> Bool isSubsumedByWith [] c d = isALSubsumedBy c d isSubsumedByWith _ _ _ = error "TBox reasoning not supported for AL"
and immediately noticed that I might also write this:
isSubsumedByWith :: TBox c -> c -> c -> Bool isSubsumedByWith [] = isALSubsumedBy isSubsumedByWith _ = error "TBox reasoning not supported for AL"
which led me to thinking about the difference between these two functions (I reason there must be a difference, because the call of 'error' is required to fulfil (terminology?) values of different types).
I think it is this: Suppose I evaluate an expression:
let s = isSubsumedByWith [foo] in seq s e
then I think the first case will return a legitimate function, albeit one that returns error when it is applied, and the second will cause an error to be returned immediately. Am I right? Is this all?
It is my understanding (someone correct me if I am wrong) that 'seq' is the one and only way to determine the difference between _|_ and \_ -> _|_ and this causes some theoretical problems. I would actually like to hear more about what sort of problems this causes from a theory point of view if anyone has some references. (I know the practical advantages of having seq in the language are great so this is just academic curiosity) John -- John Meacham - ⑆repetae.net⑆john⑈

At 11:31 08/11/04 -0800, John Meacham wrote:
On Mon, Nov 08, 2004 at 02:20:45PM +0000, Graham Klyne wrote:
I just found myself writing a function that looked like this:
isSubsumedByWith :: TBox c -> c -> c -> Bool isSubsumedByWith [] c d = isALSubsumedBy c d isSubsumedByWith _ _ _ = error "TBox reasoning not supported for AL"
and immediately noticed that I might also write this:
isSubsumedByWith :: TBox c -> c -> c -> Bool isSubsumedByWith [] = isALSubsumedBy isSubsumedByWith _ = error "TBox reasoning not supported for AL"
which led me to thinking about the difference between these two functions (I reason there must be a difference, because the call of 'error' is required to fulfil (terminology?) values of different types).
I think it is this: Suppose I evaluate an expression:
let s = isSubsumedByWith [foo] in seq s e
then I think the first case will return a legitimate function, albeit one that returns error when it is applied, and the second will cause an error to be returned immediately. Am I right? Is this all?
It is my understanding (someone correct me if I am wrong) that 'seq' is the one and only way to determine the difference between _|_ and \_ -> _|_ and this causes some theoretical problems. I would actually like to hear more about what sort of problems this causes from a theory point of view if anyone has some references. (I know the practical advantages of having seq in the language are great so this is just academic curiosity)
Developing this line... I think it may be more than *just* an academic curiosity. My intuition is that the latter of my example might actually produce a more useful diagnostic in the event of an error being generated. I used seq in my example to avoid getting tied up with laziness, but I can see it might not be possible to expose the difference without some kind of strictness being enforced. #g ------------ Graham Klyne For email: http://www.ninebynine.org/#Contact
participants (4)
-
Graham Klyne
-
Graham Klyne
-
John Meacham
-
Marcin 'Qrczak' Kowalczyk