
On Fri, Feb 5, 2010 at 9:54 PM, Mario Blažević
Victor Nazarov wrote:
Hello,
I've been writing some GUI application with Gtk2hs. It's an interpreter for lambda-calculus and combinatory logic, it's GPL and if you interested I can share it with cafe.
The problem is that the GUI code has become very ugly and I'm tempted to rewrite it totally. I've been looking forward to the FRP stuff, but I've never seen a single definition of the term. Conal Eliot's "denotational programming" is too general to be definition. I want to try Grapefruit, but I got totally lost when I see arrow notation.
I consider more lightweight and more imperative approach, something closer to CSP (Communicating Secuential Processes) then FRP. I've just crafted some sample program to illustrate my idea.
The behaviour is a monad and it's IO monad so you can do any IO (Gtk2hs) programming you wish. The differences is that you don't attach static event handlers and tries to determine what to do dependent on application state. You attach and detach handlers as much as possible. Behaviour looks like a process that can stop execution and wait for some GUI event. When event arrived it continues execution.
To summarize, the behaviour is a suspendable IO computation. It looks very much like a coroutine, in fact. I'm planning to extract the Control.Concurrent.Coroutine module [1] into a separate package soon. It implements a similar concept but generalized to transform any monad and any functorial suspension.
[1] http://hackage.haskell.org/packages/archive/scc/0.4/doc/html/Control-Concurr...
Yes, behaviour is exactly a coroutine. Your coroutine module seem cool, but I would like to have a DSL closer to GUI programming than to concurrent programming.
Do you see this approach viable. There are steel some details to emerge: * How to wait for several events * How to handle IO exceptions
I don't really know how applicable the idea is to GUI programming. That's not my area of expertise. I am surprised, though, that neither your code not your comments seem to address the issue of concurrency, as I expect that would be crucial in a GUI setting. Wouldn't you need different behaviours to run in different threads?
As I understand Gtk2hs still don't run in -threaded environment. And I've been trying to avoid multithreading as much as possible. I've already implemented exception handling through MonadError instance and multi-event waits. Now I'm trying to rewrite GUI code of my lambda-interpreter, and I'll publish it on hackage, when I am done.
Here is the code: {-# LANGUAGE ExistentialQuantification #-} ...
I don't see the purpose of your BBind constructor. It seems to me that you could simply move the first three cases of runBehaviour implementation into your >>= and get rid of the constructor. Do you need that much laziness?
I think, I need it, I can't see the way to rewrite it without intermediate data-structure. The problem is the third case: runBehaviour (BBind (BBind a f) g) = runBehaviour (a >>= (\x -> f x >>= g)) See Heinrich Apfelmus' entry in Monad.Reader to see operational view on monads. My implementation is very close to this idea. -- Victor Nazarov