Difference between revisions of "LGtk"
m (→References) |
(Changelog for 0.5.3) |
||
(18 intermediate revisions by the same user not shown) | |||
Line 1: | Line 1: | ||
[[Category:User interfaces]] |
[[Category:User interfaces]] |
||
− | == What is it? == |
||
LGtk is a lens-based API for Gtk. |
LGtk is a lens-based API for Gtk. |
||
LGtk is built on Gtk2Hs. |
LGtk is built on Gtk2Hs. |
||
+ | |||
+ | == Introduction == |
||
Most Haskellers would like to use a mature FRP-based API for creating graphical user interfaces. |
Most Haskellers would like to use a mature FRP-based API for creating graphical user interfaces. |
||
Line 9: | Line 10: | ||
LGtk has a lens-based API which fits better these user interfaces. |
LGtk has a lens-based API which fits better these user interfaces. |
||
− | == |
+ | == Internal links == |
− | |||
− | The semantics of LGtk is given by a reference implementation. |
||
− | The reference implementation is given in the following stages. |
||
− | |||
− | === Lenses === |
||
− | |||
− | LGtk use simple lenses defined in the data-lens package: |
||
− | |||
− | <haskell> |
||
− | newtype Lens a b = Lens { runLens :: a -> Store b a } |
||
− | </haskell> |
||
− | |||
− | This data type is isomorphic to <hask>(a -> b, b -> a -> a)</hask>, the well-know lens data type. |
||
− | |||
− | In certain places LGtk allows to use non-pure lenses, i.e. lenses which |
||
− | brake lens laws. Those places are explicitly marked and explained in this overview. |
||
− | |||
− | === References === |
||
− | |||
− | It is convenient to use lenses with the state monad |
||
− | ([http://www.haskellforall.com/2013/05/program-imperatively-using-haskell.html see this use case]) and the reader monad. |
||
− | |||
− | Let's call <hask>Lens s a</hask> a '''reference''' of the state monad <hask>State s</hask> and the reader monad <hask>Reader s</hask>. |
||
− | |||
− | References are distinguished from lenses, because we would like to make the program state <hask>s</hask> unaccessible to guarantee linear use of the state for example. |
||
− | |||
− | There are several ways to model references in Haskell. |
||
− | LGtk models them with type classes and associated types, but that is a technical detail here. |
||
− | |||
− | ==== Types ==== |
||
− | |||
− | Instead of giving a concrete implementation in Haskell, suppose that |
||
− | |||
− | * <hask>s</hask> is a fixed type, |
||
− | * <hask>Ref</hask>, the type of references is isomorphic to <hask>Lens s</hask>, |
||
− | * <hask>S</hask> is isomorphic to <hask>State s</hask>, |
||
− | * <hask>R</hask> is isomorphic to <hask>Reader s</hask>. |
||
− | |||
− | The isomorphisms are not exposed in the API. |
||
− | |||
− | ==== Operations ==== |
||
− | |||
− | Exposed operations of <hask>Ref</hask>, <hask>S</hask> and <hask>R</hask>: |
||
− | |||
− | * The <hask>Monad</hask> instance of <hask>S</hask> and <hask>R</hask> |
||
− | |||
− | * The monad morphism between <hask>R</hask> and <hask>S</hask> |
||
− | |||
− | <haskell> |
||
− | liftReadPart :: R a -> S a |
||
− | liftReadPart = gets . runReader |
||
− | </haskell> |
||
− | |||
− | * Reference read |
||
− | |||
− | <haskell> |
||
− | readRef :: Ref a -> R a |
||
− | readRef = reader . getL |
||
− | </haskell> |
||
− | |||
− | * Reference write |
||
− | |||
− | <haskell> |
||
− | writeRef :: Ref a -> a -> S () |
||
− | writeRef = modify . setL r |
||
− | </haskell> |
||
− | |||
− | * Lens application on a reference |
||
− | |||
− | <haskell> |
||
− | lensMap :: Lens a b -> Ref a -> Ref b |
||
− | lensMap = (.) |
||
− | </haskell> |
||
− | |||
− | * Reference join |
||
− | |||
− | <haskell> |
||
− | joinRef :: R (Ref a) -> Ref a |
||
− | joinRef = Lens . join . (runLens .) . runReader |
||
− | </haskell> |
||
− | |||
− | * The unit reference |
||
− | |||
− | <haskell> |
||
− | unitRef :: r () |
||
− | unitRef = lens (const ()) (const id) |
||
− | </haskell> |
||
− | |||
− | Note that the identity lens is '''not''' a reference because that would leak the program state <hask>s</hask>. |
||
− | |||
− | === Lens-trees === |
||
− | |||
− | TODO |
||
− | |||
− | === Effects === |
||
+ | * [[LGtk/Semantics]] |
||
− | TODO |
||
+ | * [[LGtk/ADT_lenses]] |
||
== Examples == |
== Examples == |
||
Line 133: | Line 40: | ||
<hask>action</hask> gives acces to a monad in which new references can be made by <hask>newRef</hask>. |
<hask>action</hask> gives acces to a monad in which new references can be made by <hask>newRef</hask>. |
||
− | A |
+ | A crucial feature of LGtk is that you cannot change the value of references in this monad (you can read them though). |
<hask>label</hask> gives acces to a monad in which you can read references but no reference creation or write is possible. |
<hask>label</hask> gives acces to a monad in which you can read references but no reference creation or write is possible. |
||
Line 183: | Line 90: | ||
== Changelog == |
== Changelog == |
||
+ | |||
+ | === lgtk-0.5.3 === |
||
+ | |||
+ | * bugfix: handle focus out events for entries |
||
+ | * bugfix: run postponed actions at widget initialization |
||
+ | |||
+ | === lgtk-0.5.2 === |
||
+ | |||
+ | * Better support for references with equality |
||
+ | * Documentation fixes and cleanup |
||
+ | * Inner change: safer state handling with MVars |
||
=== lgtk-0.5.1 === |
=== lgtk-0.5.1 === |
||
Line 217: | Line 135: | ||
* [http://www.reddit.com/r/haskell/comments/1cj0o6/lgtk_api_fixed/ 17 April] |
* [http://www.reddit.com/r/haskell/comments/1cj0o6/lgtk_api_fixed/ 17 April] |
||
* [http://www.reddit.com/r/haskell/comments/1f5m5j/ann_lgtk_05/ 27 May] |
* [http://www.reddit.com/r/haskell/comments/1f5m5j/ann_lgtk_05/ 27 May] |
||
+ | * [http://www.reddit.com/r/haskell/comments/1fjerf/lens_chains_lgtk_semantics_first_part/ 2 June] |
Revision as of 21:24, 15 June 2013
LGtk is a lens-based API for Gtk.
LGtk is built on Gtk2Hs.
Introduction
Most Haskellers would like to use a mature FRP-based API for creating graphical user interfaces. FRP may not be the best tool for special user interfaces, like interfaces which consists of buttons, checkboxes, combo boxes, text entries and menus only. LGtk has a lens-based API which fits better these user interfaces.
Internal links
Examples
Hello World
main = runWidget $ label $ return "Hello World!"
return
is neded because labels may be dynamic, see the next examples.
Copy
The following applications presents an entry and a label below of it. When a text is entered in the entry, the label is changed to the entered text.
main = runWidget $ action $ do
r <- newRef "enter text here"
return $ vcat
[ entry r
, label $ readRef r
]
action
gives acces to a monad in which new references can be made by newRef
.
A crucial feature of LGtk is that you cannot change the value of references in this monad (you can read them though).
label
gives acces to a monad in which you can read references but no reference creation or write is possible.
Addition
Two entries of integers and a label which shows the sum:
main = runWidget $ action $ do
r1 <- newRef (12 :: Integer)
r2 <- newRef 4
return $ vcat
[ entryShow r1
, entryShow r2
, label $ liftM show $ liftM2 (+) (readRef r1) (readRef r2)
]
Complex examples
You can find more complex examples in the source code of LGtk. More examples will be presented here also.
Status
Features of lgtk-0.5
- The API is closed, you can safely use any constructs as far as you obey the documented laws.
- Support for asynchronous events. Using LGtk is a safe way for writing multithreaded Gtk applications.
- The semantics is getting stable but it is not yet documented.
TODO list:
- Add an efficient implementation for LGtk. LGtk has only a reference implementation currently.
- Add support for styles (layout, colors, etc).
- Support more Gtk constructs.
Demo application
You can try the demo application with the following commands:
cabal install gtk2hs-buildtools cabal install lgtk lgtkdemo
Changelog
lgtk-0.5.3
- bugfix: handle focus out events for entries
- bugfix: run postponed actions at widget initialization
lgtk-0.5.2
- Better support for references with equality
- Documentation fixes and cleanup
- Inner change: safer state handling with MVars
lgtk-0.5.1
- Documentation fixes and cleanup
- Try to support Haskell Platform 2012.4.0.0
lgtk-0.5
- Do not use monadic lenses any more.
- Support for asynchronous events.
- Lazily created tabs.
- Unactive tabs are really unactive (event handlers are detached).
- File references watch the files. When the file changes, the GUI is updated.
- References with inherent identity (makes defining auto-sensitive buttons easier)
- Experimental support for colored buttons.
- More examples in the demo application.
- Lots of inner changes.
External links
Related Stackoverflow questions:
Reddit comments: