Open DylanLukes opened 13 years ago
You're right that more flexibility in deploying ProcessM would be nice, but it's a pretty big change either way.
ProcessM could be a transformer, but you'd still have to lift your stateful actions. This makes it easier to rearrange the monad stack, but it would also break existing code, not only in changing the signatures of the existing API, but would also make a mess of Remote.Call, which should generate RPC stubs.
With a hypothetical ProcessT transformer, we could write code that looks like this:
something :: ProcessT (StateT MyState IO) Int
something =
do lift $ lift $ putStrLn "Hi" -- IO action
lift $ put MyState {noodle=9} -- State action
say "Yo" -- Process action
return 3
I'm not convinced this is a huge improvement over lifting all the Process actions. But, I am open to persuasion and I would probably accept a patch.
I think ProcessT implies IO actually, so that might not work exactly like that (How would a Process work in a non-IO context?). And also, a single liftIO could be used to bring it all the way up if ProcessT StateT is a MonadIO instance.
Well, I think the crux is that StateT has only four actions which can be automatically lifted by a MonadProcess class, whereas ProcessM has many. So, with StateT MyState ProcessM ()
, all ProcessM actions must be lifted. With ProcessT (StateT MyState Identity) ()
, a type class can be used to lift get/put/gets/modify.
This is generally a bit nicer, so I'm doing this myself in my CloudHaskell-OTP project. I'm trying to generally put a "nicer" layer of abstraction on top. i.e, almost every OTP process passes State to itself, encompassing the action in the state monad makes for some prettier code, especially in combination with Data.Lens
.
I may submit a patch, maybe not...
I took a look at your OTP project and it looks awesome. I'd love to help.
In regard to ChildSpec
, though, I think you'll need to use Closure
; Haskell is lazy but ProcessM
but process spawning isn't.
Ah thanks! That's a very good point :).
I'm very busy with other work, but I'm trying to work a little on this here and there. It's mostly for personal projects... but I'll try to keep it generalized.
In some examples I've been writing, I've been trying to use StateT MyState ProcessM (). Generally the issue with this is that all of the ProcessM stuff has to be lifted. So there are two solutions.
Make ProcessM a transformer so I can use MonadState.
Add a MonadProcessM class I can instance my monad stack with so I can lift the stuff up automatically.
Or, you know, both.