Michael, I think what you're trying to do is perfectly doable in Haskell and I think the right tool for it is arrows, as Tomasz Zielonka mentioned before. I suggest you take a look at the following paper which uses arrows to enforce security levels in the code: http://www.cis.upenn.edu/~stevez/papers/abstracts.html#LZ06a
Cheers, Josef On 6/25/07, Michael T. Richter <[EMAIL PROTECTED]> wrote:
On Mon, 2007-25-06 at 12:19 +0300, Benja Fallenstein wrote: 2007/6/25, Michael T. Richter <[EMAIL PROTECTED]>: OK, just to prevent this getting side-tracked: I'm absolutely uninterested in the results of performActionA before determining if performActionB is permitted/possible/whatever. Think more in terms of security permissions or resource availability/claiming than in terms of chaining results. I want to know before I begin to collect the results of performAction* that I will actually stand a chance at getting results at all. Uh, the posts you quote were precisely about how to do that. No side-tracking going on. :-) It looked to me like there were people arguing about whether the "x" returned from one action was going to be used in the next action. Let me try and rephrase the question. [image: :)] A conventional approach to what I'm doing would be something like this (in bad pseudocode): doStuff(): if checkPossible([opA, opB, opC]): A B C else: exception "Preconditions not met" My objection to this is its error-prone scaffolding: 1. There's no enforced link between the checking operations and the actual operations. By mistake or by deliberate action it is possible to put operations in the main body which have not been checked by the guards. 2. As code evolves and changes, it is very easy to have the check diverge from the contents of the body as well. Now if the actions were trivial or easily reversible, an alternative model is something like this (in bad pseudocode) where it's assumed that each operation checks for its privileges/capabilities/whatever as part of its operation: doStuff2(): A try: B try: C catch: undoB throw catch: undoA This looks to me like Don Stuart's "executable semi-colons" and could be coded as a pretty conventional monad (unless my eyes are deceiving me). But if doing A, say, involved expensive operations (think: generating an RSA key or making a database connection on a heavily-loaded server) or if doing B involved modifying some external state that is difficult to undo this is a less-than-ideal model. Let's say that C fails for whatever reason (insufficient privileges, the database server is dead, the phase of the moon is wrong for the species of chicken sacrificed at the keyboard -- anything), then we've got time wasted in A and B has just changed something we can't easily unchange. So I'd like some way of getting the automated check of permission/capability/availability/whatever done before performing the actual actions. Now in a language where functions are identifiable types, a solution could look like this (among a myriad of other possible solutions): check(Operation): case Operation of: A: return checkConditionA B: return checkConditionB C: return checkConditionC runStuff(actions): for each action in actions: if not check(action.left): throw CheckFailure for each action in actions: action.left(action.right) doStuff3(): actions=[(A, a_args), (B, b_args), (C, c_args)] try: runStuff(actions) catch CheckFailure: actions=nil The check() function called here can use the identity of the action provided plus any information provided externally (network connections open, permissions available, etc.) to pass/fail the capabilities/resources/whatever and the action's execution is deferred until the check has passed. The action's check *AND* its execution is unavailable to the programmer so there's less room for fraud and oversight and all the other things which make programs buggy and unreliable and such joys to work with both as a programmer and as a user. In fact with languages as malleable as Ruby (or possibly even Python) some of the ugly scaffolding above could be made to vanish behind the scenes leaving pretty clean code behind. (Uglier languages like C/C++, of course, would leave all the scaffolding lying around, but it would still be doable.) But of course this can't be done in Haskell this way because functions aren't items in Haskell. There is no function equality check. My check() function can't look like: check :: (a->b) check A = ... check B = ... check C = ... check _ = error "no such function" This leaves me in a position I can't think myself out of (hence the cry for help). I'd like it to be possible to have a do block with as little visible scaffolding as possible (ideally *none*) where I can do the equivalent of doStuff3() and runStuff() from the above pseudocode. Now here's the tricky part.... I'd ideally like to be able to do this so that it would be possible to start with the doStuff2 implementation behind the scenes (check as you go) and then, by changing the scaffolding behind the scenes, do the doStuff3() implementation *without touching a line of client code*. In effect I'd like to be able to change computing strategies on the fly without the client code having to be modified. If we look at my doStuff3() as an example, for instance, I could switch it over from a pre-check to a check-as-you-go system pretty easily by modifying runStuff() and the check(). runStuff() would be modified to interleave the check with the call and check would be modified to return an undo operation kept in an accumulator by runStuff() or nil. If nil is returned, the list of undo operations maintained by runStuff would get executed and the failure signalled. Does this make more sense now? And can it be done somehow in Haskell? -- *Michael T. Richter* <[EMAIL PROTECTED]> (*GoogleTalk:* [EMAIL PROTECTED]) *Those who have learned from history are bound to helplessly watch it repeat itself. (Albert Y. C. Lai)* _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
<<inline: smiley-3.png>>
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe