Personal tools

PropLang

From HaskellWiki

(Difference between revisions)
Jump to: navigation, search
(Thoughts by)
Line 15: Line 15:
 
     "Word count: " ++ show (length $ words x))
 
     "Word count: " ++ show (length $ words x))
  
== The Var concept ==
+
== Overview ==
  
This is the low level stuff, on which the library will be built
+
There are events, you can register to be notified when an event fires by doing
  
  data Var a = ...
+
  event += handler
data Notify = ...
+
  
get :: Var a -> IO a
+
There are variables, which have events which fire, and a value which you can set and get.
set :: Var a -> a -> IO ()
+
addNotify :: Var a -> (a -> IO ()) -> IO Notify
+
remNotify :: Notify -> IO ()
+
  
  newVar :: a -> IO (Var a)
+
  variable <- newVar "value"
 +
variable += handler
 +
variable -< "value"
 +
x <- getVal variable
  
== A concrete implementation of Var ==
+
There are objects, objects have properties. A property is just a variable.
  
One thing to avoid, global state that needs a specific init function
+
window!text += handler
 +
window!text -< "Titlebar text"
  
data Var a = Var {value :: IORef a,
+
There are bindings which relate variables.
                  notifyId :: IORef Integer,
+
                  notifys :: IORef [(Integer, a -> IO ())],
+
                  source :: IORef (Maybe Notify)}
+
  
  data Notify = Notify {notifyId :: Integer, notifys :: IORef [(Integer, a -> IO ())]}
+
<haskell>
 +
-- the window text is the variable
 +
  window!text =<= variable
 +
-- the window text is the variable, but upppercase
 +
window!text =< with1 variable (map toUpper)
 +
-- combine the two texts to create the window text
 +
window!text =< with2 variable1 variable2 (++)
 +
</haskell>
  
newVar :: a -> IO (Var a)
+
If any of the values on the RHS of a binding change, then the LHS is updated.
newVar x = do v <- newIORef x
+
              n <- newIORef []
+
              c <- newIORef 0
+
              a <- newIORef Nothing
+
              return $ Var v c n a
+
 
+
get :: Var a -> IO a
+
get var = readIORef (value var)
+
 
+
set :: Var a -> a -> IO ()
+
set var x = do n <- readIORef (notifys var)
+
                writeIORef (value var) x
+
                mapM_ (\(a,b) -> b x) n
+
 
+
addNotify :: Var a -> (a -> IO ()) -> IO Notify
+
addNotify var f = do n <- readIORef (notifys var)
+
                      c <- readIORef (notifyId var)
+
                      writeIORef (notifyId var) (c+1)
+
                      writeIORef (notifys var) ((c, f) : n)
+
                      return $ Notify c (notifys var)
+
 
+
remNotify :: Notify -> IO ()
+
remNotify notify = do n <- readIORef (notifys notify)
+
                      writeIORef (notifys notify) (filter (\x -> fst x /= notifyId notify) n)
+
 
+
== Object layering ==
+
 
+
textBox!text -< "test"
+
filename <- newVar Nothing
+
addNotify filename hatCover
+
lbl!text =< with filename $ \x ->
+
                  case x of
+
                      Nothing -> "Select a file"
+
                      Just x -> "Loaded: " ++ x
+
 
+
 
+
where
+
 
+
(!) :: GtkObject -> GtkProp -> Var a -- ignoring lots of details here
+
(-<) :: Var a -> a -> IO ()
+
(=<) :: Var a -> Action a b -> IO ()
+
 
+
with :: Var a -> (a -> b) -> Action a b
+
 
+
== Implementation of Object Layering ==
+
 
+
data Action a b = Action (Var a) (a -> b)
+
 
+
with :: Var a -> (a -> b) -> Action a b
+
with var f = Action var f
+
 
+
(-<) :: Var a -> a -> IO ()
+
(-<) var val = set var val
+
 
+
(=<) :: Var a -> Action a -> IO ()
+
(=<) dest (Act src f) = do srcOld <- readIORef (source dest)
+
                            when (isJust srcOld) $ remNotify (fromJust srcOld)
+
                            note <- addNotify src (\x -> set dest (f x))
+
                            writeIORef (source dest) (Just note)
+
 
+
== Implementation of Gtk Layering ==
+
 
+
class TextProvider a where
+
    text :: a -> Var String
+
 
+
instance TextProvider TextView where
+
    text x = ...
+
 
+
txt :: TextView
+
 
+
(!) :: a -> (a -> b) -> b
+
object ! prop = prop object
+
 
+
txt!text :: Var String
+

Revision as of 08:37, 24 July 2006

A design for a GUI library which is more like Haskell and less like C. To be written over Gtk2Hs.

Link: http://www.cse.unsw.edu.au/~chak/haskell/ports/

1 Thoughts by

Neil Mitchell, Duncan Coutts


For a darcs repo see: http://www.cs.york.ac.uk/fp/darcs/proplang/

In particular check out Sample.hs, I am particularly proud of the word count:

sb!text =< with1 (txt!text) (\x ->
    "Word count: " ++ show (length $ words x))

2 Overview

There are events, you can register to be notified when an event fires by doing

event += handler

There are variables, which have events which fire, and a value which you can set and get.

variable <- newVar "value"
variable += handler
variable -< "value"
x <- getVal variable

There are objects, objects have properties. A property is just a variable.

window!text += handler
window!text -< "Titlebar text"

There are bindings which relate variables.

 -- the window text is the variable
 window!text =<= variable
 -- the window text is the variable, but upppercase
 window!text =< with1 variable (map toUpper)
 -- combine the two texts to create the window text
 window!text =< with2 variable1 variable2 (++)

If any of the values on the RHS of a binding change, then the LHS is updated.