[Haskell-cafe] Practical Haskell question.
lemming at henning-thielemann.de
Mon Jun 25 04:29:14 EDT 2007
On Mon, 25 Jun 2007, Daniil Elovkov wrote:
> 2007/6/25, Michael T. Richter <ttmrichter at gmail.com>:
> > Now I've got a situation I can't figure out how to resolve. I want to have a set of actions which are executed sequentially, but which, before I even start to execute the first one, have been inspected for legality and/or plausibility. Consider this kind of sequence:
> > do
> > x <- performActionA
> > y <- performActionB
> > z <- performActionC
> > return $ calculateStuff x y z
> > Now obviously this is going to be in a monad of some kind. Were this a regular, run-of-the-mill program I'd just use the IO monad. But what I want to do instead is, before executing any of the perform* functions, check that the actions desired are actually permitted (or possible) given a set of circumstances. For example let's say it's a permissions issue and performActionB can only be done if I'm root. If I'm not root I don't want performActionA done because I can't complete the transaction. (Maybe ActionA is non-reversible, say.) Or let's say this is code that's accessing databases on the network. If the network link to C can't be established, I don't want to screw around with A and B's links at all -- it's too expensive, too time-consuming or whatever.
> > Were I programming this in C, C++, Python, Ruby, etc. I could do this in my sleep. Functions are addresses (C/C++) or objects with an ID (Python/Ruby) so it's possible to take them and do some kind of check based on identities before executing things (although the scaffolding around this would be nontrivial in any of these languages except, possibly, Ruby). Functions in Haskell don't have this property, however, so I can't figure out what I'd do to perform similar work. I'm sure there's a way to do it, but I just can't see it.
> Hello, I would suggest defining your own data type an instance of
> monad. The sense of it would be 'sequantial IO operations which you
> can do some checks on'.
> It would have some flags and properties along with the IO computation
> itself. Operations (>>) and (>>=) would construct more complex
> computations from simple ones, and since your data type is not opaque
> to you, you could inspect those complex computations for properties,
> too. Including synergetic ones, like 'this is never done, after that
> has been invoked...'
This is easier said than done.
Imagine all performActions contain their checks somehow. Let
performActionB take an argument.
> x <- performActionA
> y <- performActionB x
> z <- performActionC
> return $ calculateStuff x y z
Now performActionB and its included check depend on x. That is, the check
relies formally on the result of performActionA and thus check B must be
performed after performActionA.
More information about the Haskell-Cafe