2007/6/25, Michael T. Richter <[EMAIL PROTECTED]>:

 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...'

And then you will have to have a conventional runYourMonad function,
which will be an IO computation. It could be the place, where the
validity check occurs.

The data type could be the list of operations, or probably a tree-like
structure to account for branching.

The downside is you would have to supply those flags, but you could
define some lifting functions, like
flag :: Flags -> IO a -> YourMonad a
do
 flag OnlyRoot ioOperation
 flag someComplexFlag anotherOperation


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

Reply via email to