Re: [Haskell] Arrows GUI Library Based on GTK+

On Sat, Mar 19, 2005 at 12:17:46PM -0700, Kevin Atkinson wrote:
On Sat, 19 Mar 2005 ross@soi.city.ac.uk wrote:
I would also have expected loopFG to have been defined using fixIO.
Could you be more specific. Ie How?
For the type definitions newtype FG' a b = FG' (Control -> a -> IO (Control, b)) newtype FG a b = FG (FGState -> IO (FG' a b, FGState)) newtype Container a b = Container (FG ([WidgetP], a) b) the usual instances would be (give or take a ~): instance Arrow FG' where arr f = FG' $ \ c x -> return (c, f x) FG' f >>> FG' g = FG' $ \ c x -> do (c', x') <- f c x g c' x' first (FG' f) = FG' $ \ c (x, y) -> do (c', x') <- f c x return (c', (x', y)) instance ArrowLoop FG' where loop (FG' f) = FG' $ \ c x -> do (c', x', _) <- mfix $ \ ~(_, _, y) -> do ~(c', ~(x', y')) <- f c (x, y) return (c', x', y') return (c', x') instance Arrow FG where arr f = FG $ \ s -> return (arr f, s) FG f >>> FG g = FG $ \ s -> do (f', s') <- f s (g', s'') <- g s return (f' >>> g', s'') first (FG f) = FG $ \ s -> do (f', s') <- f s return (first f', s') instance ArrowLoop FG where loop (FG f) = FG $ \ s -> do (f', s') <- f s return (loop f', s') instance Arrow Container where arr f = Container (arr (f . snd)) Container f >>> Container g = Container $ arr (\ (ws, a) -> (ws, (ws, a))) >>> second f >>> g first (Container f) = Container $ arr (\ ~(ws,~(x,y)) -> ((ws,x),y)) >>> first f instance ArrowLoop Container where loop (Container f) = Container $ loop (arr (\ ((ws,x),y) -> (ws,(x,y))) >>> f) The FG instances seem to match yours, except for ArrowLoop.

On Sun, 20 Mar 2005 ross@soi.city.ac.uk wrote:
On Sat, Mar 19, 2005 at 12:17:46PM -0700, Kevin Atkinson wrote:
On Sat, 19 Mar 2005 ross@soi.city.ac.uk wrote:
I would also have expected loopFG to have been defined using fixIO.
Could you be more specific. Ie How?
For the type definitions
newtype FG' a b = FG' (Control -> a -> IO (Control, b)) newtype FG a b = FG (FGState -> IO (FG' a b, FGState)) newtype Container a b = Container (FG ([WidgetP], a) b)
the usual instances would be (give or take a ~):
instance ArrowLoop FG' where loop (FG' f) = FG' $ \ c x -> do (c', x', _) <- mfix $ \ ~(_, _, y) -> do ~(c', ~(x', y')) <- f c (x, y) return (c', x', y') return (c', x')
I must admit that I am baffled by what this is doing. But I don't think it has the semantics I want. When I try substituting your code in I get "Exception: <<loop>>". I have reworked the way loops are handled. Please have a look at the new code at http://www.haskell.org/arrows/. -- http://kevin.atkinson.dhs.org

On Tue, 22 Mar 2005, Kevin Atkinson wrote:
On Sun, 20 Mar 2005 ross@soi.city.ac.uk wrote:
On Sat, Mar 19, 2005 at 12:17:46PM -0700, Kevin Atkinson wrote:
On Sat, 19 Mar 2005 ross@soi.city.ac.uk wrote:
I would also have expected loopFG to have been defined using fixIO.
Could you be more specific. Ie How?
For the type definitions
newtype FG' a b = FG' (Control -> a -> IO (Control, b)) newtype FG a b = FG (FGState -> IO (FG' a b, FGState)) newtype Container a b = Container (FG ([WidgetP], a) b)
the usual instances would be (give or take a ~):
instance ArrowLoop FG' where loop (FG' f) = FG' $ \ c x -> do (c', x', _) <- mfix $ \ ~(_, _, y) -> do ~(c', ~(x', y')) <- f c (x, y) return (c', x', y') return (c', x')
I must admit that I am baffled by what this is doing. But I don't think it has the semantics I want. When I try substituting your code in I get "Exception: <<loop>>". I have reworked the way loops are handled. Please have a look at the new code at http://www.haskell.org/arrows/.
Make that http://kevin.atkinson.dhs.org/fg/. Sorry need to pay attention when I paste URL's :( -- http://kevin.atkinson.dhs.org

On Tue, Mar 22, 2005 at 09:52:04AM -0700, Kevin Atkinson wrote:
I must admit that I am baffled by what this is doing. But I don't think it has the semantics I want. When I try substituting your code in I get "Exception: <<loop>>".
I could have made it a bit simpler: instance ArrowLoop FG' where loop (FG' f) = FG' $ \ c x -> do (c', ~(x', _)) <- mfix $ \ ~(_, ~(_, y)) -> f c (x, y) return (c', x') This executes f once only, with y bound to the third component of the output of f. This isn't available until f finishes, so any attempt to examine it while f is running will lead to <<loop>>, but f can pass it around, and store it in data structures; it can even create cyclic structures. (Under the hood, the IO instance of mfix starts with y bound to an exception, and updates it when f finishes, a bit like what you're trying to do with IORef's, except that existing references to y then point at the updated thing.) Your definition runs f once with undefined as the last argument to get a value for y to supply to a second run. Presumably the things you're doing with Control need to change too, and I don't understand all that, but I expect that the mfix version could be made to work, and would do less work.

On Tue, 22 Mar 2005 ross@soi.city.ac.uk wrote:
On Tue, Mar 22, 2005 at 09:52:04AM -0700, Kevin Atkinson wrote:
I must admit that I am baffled by what this is doing. But I don't think it has the semantics I want. When I try substituting your code in I get "Exception: <<loop>>".
I could have made it a bit simpler:
instance ArrowLoop FG' where loop (FG' f) = FG' $ \ c x -> do (c', ~(x', _)) <- mfix $ \ ~(_, ~(_, y)) -> f c (x, y) return (c', x')
This executes f once only, with y bound to the third component of the output of f. This isn't available until f finishes, so any attempt to examine it while f is running will lead to <<loop>>, but f can pass it around, and store it in data structures; it can even create cyclic structures. (Under the hood, the IO instance of mfix starts with y bound to an exception, and updates it when f finishes, a bit like what you're trying to do with IORef's, except that existing references to y then point at the updated thing.) Your definition runs f once with undefined as the last argument to get a value for y to supply to a second run. Presumably the things you're doing with Control need to change too, and I don't understand all that, but I expect that the mfix version could be made to work, and would do less work.
I think I understand it more, but I am not sure it will do what I want. For one thing f still needs to know when it can examine its input thus, still needing an initializing pass. Please have a look at the new code. I have reworked how loops are handled and no longer use Control. Also the state variable is now needed in separate functions. Thus I am not sure I can use the mfix trick to hide the state.
participants (2)
-
Kevin Atkinson
-
ross@soi.city.ac.uk