Difference between revisions of "PropLang"

From HaskellWiki
Jump to navigation Jump to search
(Categorize)
 
(4 intermediate revisions by one other user not shown)
Line 1: Line 1:
  +
[[Category:User interfaces]] [[Category:Proposals]] [[Category:Libraries]]
 
A design for a GUI library which is more like Haskell and less like C. To be written over Gtk2Hs.
 
A design for a GUI library which is more like Haskell and less like C. To be written over Gtk2Hs.
   
Line 5: Line 6:
 
== Thoughts by ==
 
== Thoughts by ==
   
Neil Mitchell, Duncan Coutts
+
Neil Mitchell, some patches from Joachim Breitner, discussions and help from Duncan Coutts
 
   
 
For a darcs repo see: http://www.cs.york.ac.uk/fp/darcs/proplang/
 
For a darcs repo see: http://www.cs.york.ac.uk/fp/darcs/proplang/
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
 
 
data Var a = ...
 
data Notify = ...
 
 
get :: Var a -> IO a
 
set :: Var a -> a -> IO ()
 
addNotify :: Var a -> (a -> IO ()) -> IO Notify
 
remNotify :: Notify -> IO ()
 
 
newVar :: a -> IO (Var a)
 
 
== A concrete implementation of Var ==
 
 
One thing to avoid, global state that needs a specific init function
 
 
data Var a = Var {value :: IORef a,
 
notifyId :: IORef Integer,
 
notifys :: IORef [(Integer, a -> IO ())],
 
source :: IORef (Maybe Notify)}
 
 
data Notify = Notify {notifyId :: Integer, notifys :: IORef [(Integer, a -> IO ())]}
 
 
newVar :: a -> IO (Var a)
 
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)
 
   
  +
There are events, you can register to be notified when an event fires by doing
with :: Var a -> (a -> b) -> Action a b
 
with var f = Action var f
 
   
  +
event += handler
(-<) :: Var a -> a -> IO ()
 
(-<) var val = set var val
 
   
  +
There are variables, which have events which fire, and a value which you can set and get.
(=<) :: 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)
 
   
  +
variable <- newVar "value"
== Implementation of Gtk Layering ==
 
  +
variable += handler
  +
variable -< "value"
  +
x <- getVal variable
   
  +
There are objects, objects have properties. A property is just a variable.
class TextProvider a where
 
text :: a -> Var String
 
   
  +
window!text += handler
instance TextProvider TextView where
 
  +
window!text -< "Titlebar text"
text x = ...
 
   
  +
There are bindings which relate variables.
txt :: TextView
 
   
  +
-- the window text is the variable
(!) :: a -> (a -> b) -> b
 
  +
window!text =<= variable
object ! prop = prop object
 
  +
-- 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.
txt!text :: Var String
 

Latest revision as of 21:21, 23 June 2007

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/

Thoughts by

Neil Mitchell, some patches from Joachim Breitner, discussions and help from 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))

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.