MetaHDBC paper (draft)

September 18, 2008

In May I started a Haskell-cafe discussions, where I proposed using
Template Haskell to do type-safe database access. The idea got well
received and turned into the MetaHDBC library.

Concurrently with development I also wrote a paper describing
MetaHDBC. I have never writing a paper before, and I therefore tried
to imitate the best by following Simon PJ’s slides and video about
writing papers
.

A draft of the paper can be found here. Your opportunity to
influence the paper is large, as my limited paper-writing experience
means I have little preconception about what a good paper looks
like. I would especially like comments about the overall quality of
the paper, can it be called scientific and comments about anything I
could do to improve the paper. And remember, if commenting, honest is
better than polite.

Using WxGeneric

May 21, 2008

As I posted earlier AutoForms has been reimplement in a new library called WxGeneric. In this post we look at using WxGeneric from a purely practical perspective.

To understand this post you should already be familiar with Haskell and WxHaskell.

The short introduction to WxGeneric is that it is a library to generically construct WxHaskell widgets, by looking at the structure and names of types. If you want more background information, you should look at AutoForms, which is the library WxGeneric is based upon.

Installation

Before installing WxGeneric you must install the following dependencies:

The hard to install dependencies are GHC and WxHaskell (both of which you properly already got). The rest are installed as ordinary cabalized packages. See here for general information about installing cabalized packages.

Next download and install WxGeneric like a normal cabalized package.

Tuple example

We will start with a small example which converts a tuple (Int, String, Double) into a WxHaskell widget. Below you can see the example code. The code which is WxGeneric specific are italicized. The rest is ordinary WxHaskell code. The most interesting new function is genericWidget, which is used to construct widgets generically. This function takes two parameters – a frame and the value to turn into a widget. Also we have a new attribute called widgetValue, which can be used to get and set the value of a widget. The rest of the code is ordinary WxHaskell code:

module TupleExample where

import Graphics.UI.WxGeneric
import Graphics.UI.WX

main :: IO ()
main = start $
       do f <- frame [ text := "Tuple Example" ]
          p <- panel f []
          en <- genericWidget p (3 :: Int, "Hans", 5.5 :: Double)
          b <- button p [ text := "&Print tuple"
                        , on command := get en widgetValue >>= print ]
          set f [ layout := container p $ row 10 [ widget en, widget b ] ]

And the resulting GUI:

Tuple Example

Alarm example

In this example we will see how to convert a programmer defined data type into a widget. We have chosen an Alarm data type, which contains an alarm name and time of day (measured in minutes). The code:

{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses
  , TemplateHaskell, UndecidableInstances #-}

module Alarm where

import Graphics.UI.WxGeneric
import Graphics.UI.SybWidget.MySYB

import Graphics.UI.WX
import Graphics.UI.WXCore

data Minutes = Minutes Int deriving (Show, Eq)
data Alarm = Alarm { name :: String
                   , timeOfDay :: Minutes
                   } deriving (Show, Eq)

$(derive [''Minutes,''Alarm])

instance WxGen Alarm
instance WxGen Minutes

main :: IO ()
main = start $
       do f <- frame [ text := "Alarm Example" ]
          p <- panel f []
          en <- genericWidget p (Alarm "My alarm" $ Minutes 117)
          b >= print ]
          set f [ layout := container p $ row 10 [ widget en, widget b ] ]

The three italicized lines are the boilerplate needed to convert the Alarm type into widgets. Derive is a Template Haskell function which derives instances for the two type classes Data and Typeable. In this case we derive instances for the two data types Minutes and Alarm. We also needs to specify that Alarm and Minutes can be turned into widgets. That is done by the two instance declarations. The rest is similar to the previous example.

And the resulting GUI:

Alarm Example

Specializing Alarm

Presenting time of day as minutes is not particular user friendly. However it is convenient to model it as such. Thus we would like to present the minutes differently to the user, as they are stored in the model. WxGeneric supports this:

{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses
  , TemplateHaskell, UndecidableInstances #-}

module AlarmSpecialized where

import Graphics.UI.WxGeneric
import Graphics.UI.SybWidget.MySYB

import Graphics.UI.WX
import Graphics.UI.WXCore

import Control.Monad

data Minutes = Minutes Int deriving (Show, Eq)
data Alarm = Alarm { name :: String
                   , timeOfDay :: Minutes
                   } deriving (Show, Eq)
$(derive [''Minutes,''Alarm])

instance WxGen Alarm

instance WxGen Minutes where
    mkWid m' = toOuter (valuedCompose helper)
        where helper p = 
                  do changeVar <- varCreate (return ())
                     
                     hours   <- hslider p True 0 23 [ selection := fst $ minutes2Clock m' ]
                     minutes <- hslider p True 0 23 [ selection := snd $ minutes2Clock m' ]
                     
                     let setChangeVar x = do set hours   [ on command := x ]
                                             set minutes [ on command := x ]
                         lay = grid 10 10 [ [ label "Hours: ", fill $ widget hours ]
                                          , [ label "Minutes: ", fill $ widget minutes ] ]
                         getVal = liftM2 clock2Minutes (get hours selection) (get minutes selection)
                         setVal ys = do let (h, m) = minutes2Clock ys
                                        set hours [selection := h]
                                        set minutes [selection := m]
                     return ( lay, getVal, setVal
                            , varGet changeVar, setChangeVar
                            )
              minutes2Clock (Minutes m) = (m `div` 60, m `mod` 60)
              clock2Minutes h m         = Minutes (60*h + m)

main :: IO ()
main = start $
       do f <- frame [ text := "Alarm Specialized Example" ]
          p <- panel f []
          en <- genericWidget p (Alarm "My alarm" $ Minutes 117)
          b >= print ]
          set f [ layout := container p $ row 10 [ fill $ widget en, widget b ]
                , size := Size 550 165 ]

The italicized code show the interesting lines. These lines specifies how to present the Minutes type to the user. It is done by making Minutes an instance of WxGen. We use two WxGeneric functions to help us – toOuter and valuedCompose. valuedCompose uses the helper function, which must return a 5-tuple consisting of:

  1. Layout
  2. a get value action
  3. a set value action
  4. a get change listener action
  5. a set change listener action

the rest of the code should be familiar.

And the resulting GUI:

Alarm Specialized Example

The code has blown up in size, and you may think that this do not free you from a lot of work as compared to making the GUI directly in WxHaskell. However, we can reuse the specialization of the Alarm type in other data types. For example if we have big data type Foo, which includes the Alarm type, we just need to make sure that the Alarm WxGen-instance is in scope and it is automatically used when turning Foo into a widget.

Also the specialization can be made more general. We can make a WxGen instance for all lists. Indeed, the list instance is already included in the distribution of WxGeneric.

Modeling Alarm using a data type

Specializing the Alarm type as done in the last section may seem a little troublesome. And indeed there is another way:

{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses
  , TemplateHaskell, UndecidableInstances #-}

module AlarmMapValue where

import Graphics.UI.WxGeneric
import Graphics.UI.SybWidget.MySYB

import Graphics.UI.WX
import Graphics.UI.WXCore

data Minutes = Minutes Int deriving (Show, Eq)
data Alarm = Alarm { name :: String
                   , timeOfDay :: Minutes
                   } deriving (Show, Eq)
data UserTime = UserTime { hour   :: Int
                         , minute :: Int
                         } deriving (Show, Eq)

$(derive [''Minutes,''UserTime,''Alarm])

instance WxGen UserTime
instance WxGen Alarm

instance WxGen Minutes where
    mkWid m' =
        let minutes2UserTime (Minutes m)    = UserTime (m `div` 60) (m `mod` 60)
            userTime2Minutes (UserTime h m) = Minutes (60*h + m)
        in mapValue userTime2Minutes (const minutes2UserTime) (mkWid (minutes2UserTime m'))

main :: IO ()
main = start $
       do f <- frame [ text := "Alarm Map Value" ]
          p <- panel f []
          en <- genericWidget p (Alarm "My alarm" $ Minutes 117)
          b >= print ]
          set f [ layout := container p $ row 10 [ widget en, widget b ]
                , size := Size 275 165 ]

In stead of modeling the interface using WxHaskell, toOuter and valuedCompose, we model it by another data type (UserTime). In the Minutes instance of WxGen we then describe how to translate between UserTime and Minutes.

And the resulting GUI:

Alarm Specialized by mapValue

Your Turn

Now it is your turn to play around with WxGeneric and maybe integrate WxGeneric into some of your WxHaskell projects. You will properly find that WxGeneric’s on-line available Haddock docs are useful. I would love to get feedback about your experiences.

Introducing WxGeneric

May 3, 2008

I recently decided to rethink and reimplement AutoForms. This post will be the first of a series that explains the hows and whys of this reimplementation.

Why AutoForms need a replacement

AutoForms started simply as a library to generically construct GUI forms, such as a settings dialog. But as development has progressed more and more features has been been added. It has gotten to the point where AutoForms tries to be a complete GUI library on top of WxHaskell, in stead of just a library to generically construct widgets in cooperation with WxHaskell.

The feature creep has let to several problems:

  • Less separation of concerns than possible
  • Too much to maintain and develop
  • For potential users of a AutoForms I am asking a lot, as they will have to understand a hole new and complex library.
  • By exploring many different features, non have really been explored to a satisfactory level. AutoForms has become Jack of all trades, master of none.

I have dealt with these issues in two ways. Firstly I have created an interface to AutoForms (called AFWx) which is very simple for a person that already knows WxHaskell. Secondly to better separate concerns, I have been factoring out the different parts into independent modules.

While these remedies have helped, it was not enough. I wanted a library that focused on generically constructing Widgets from data types. As such, large parts of the code in AutoForms were unneeded. And large parts needed to be changed. Therefore starting from scratch seemed attractive. While I was not sure it was the best choice it did seem like an experiment worth performing. And in retrospect I think it turned out really well.

Another issue that led me to reimplementation were composability. Just like most data types are composed of other data types, a library like AutoForms needs to compose widgets to bigger widgets. Unfortunately WxHaskell lacks in composability. Thus AutoForms contains the WxM monad to compose widgets. The interface of the WxM monad is considerably different from ordinary WxHaskell code and those places a burden on the user. But as I recently discovered it is possible to achieve composability, while still keeping the WxHaskell look and feel. This makes a strong argument for scraping the WxM monad. And as the WxM Monad is a central piece of AutoForms, it also makes a strong argument for reimplementing AutoForms.

The Reimplementation

The reimplementation resulted in not one, but two new libraries. The first library is called WxGeneric and constructs widgets generically. In contrast to AutoForms, it do not try to reinvent the GUI library. While it does make GUI creation easier, most of the GUI application code will still look like ordinary WxHaskell code. Indeed most of the GUI application code will call WxHaskell directly.

When constructing AutoForms, I discovered that some of the hardest to implement code was not specific to any one GUI toolkit. It therefore seemed natural to abstract this code into a separate library. This library is called SybWidget and WxGeneric builds upon it. However, as it is very difficult to make a generalization from just one example, I also refactored AutoForms to use SybWidget. The refactoring indeed resulted in changes to SybWidget that made it more generally useful. It is my hope that GUI toolkits similar to WxHaskell (like Gtk2Hs) will find SybWidget useful and implement there own generic widget libraries.

Separating the WxHaskell specific parts from the rest, allowed me to make a library that do not use the IO monad. This makes it possible to test SybWidget with QuickCheck. For some functions the important aspect to test was not so much varying values, but varying types. Here QuickCheck approach do not make much sense and I opted for HUnit instead. I use Haskell Program Coverage for measuring SybWidget’s test coverage.

Future of AutoForms

The simplicity of WxGeneric (as compared to AutoForms) is very attractive, but it is not without cost either. For example AutoForms tries to be “intelligent” about the automatic layout of widgets. This “intelligence” will be lost when using WxGeneric. Also AutoForms has better static type safety than both WxGeneric and WxHaskell. In the future I might try to develop these ideas further. Either as part of AutoForms or in a separate library. But I do not think that these features should be included in WxGeneric. It should be as it is, a simple library to generically construct widgets.

The next post

In the next post we will look at how to use WxGeneric. The impatient can have a look at the darcs repository and the documentation.

Introduction

Currently there is no type safe way to make composite widgets with wxHaskell. We can compose two widgets and present them in a GUI. However, we cannot (type safely) compose two widgets into a larger widget, that behaves similarly to ordinary wxHaskell widgets (the Window w -kind). The only solutions that I have found is the CustomControls example in wxHaskell repository and as explained in this mailinglist post. Neither of them is type safe. These examples use unsafe casting of attributes and unsafe casting of the composite widget. Also as seen in the latter example, when widgets needs state they must be kept in a global hashtable, which results in more safety issues. The hashtable is created using unsafePerformIO.

Composability is important for most (maybe any) programming abstraction, and thus we would also like it for wxHaskell. Composability is also common in other GUI toolkit like AWT for Java.

In this post I will propose how we could add composability to wxHaskell.

The source code for this proposal can be found here Composite.hs, here ListExample.hs, and here IntEntryExample.hs.

In this post application programmer will refer to a person implementing a GUI application. Library programmer will refer to a person implementing the wxHaskell library.

Goals

But before going into details, I will state which goals I think is important for composing widgets:

  1. the composite should behave like an ordinary widget to the eyes of the application programmer
  2. be safe to use
  3. be easy to use
  4. simple implementation

The first goal means that the composite type should implement many (if not all) of those type classes that wxHaskell widgets normally implements.

As stated above, current ways of making composite widgets involves unsafe type casting. This is of cause less than ideal. We do not want this or similar risky code.

And lastly, we would of cause want composing to be as easy as possible. Both for the application programmer and the wxHaskell library programmer.

How to compose widgets

In this section I will describe how the application programmer creates new composite widgets, rather than how the library programmer implements the composer functions, which will be shown in the next section. We will show how to compose widgets using two examples.

We create new widgets using the compose function:

compose :: (Panel () -> IO (Layout, super, user))
        -> Window w -> [Prop (Composite super user)] -> IO (Composite super user)

which takes an IO action as input. The action should return a Layout, a super-type, and a user-type. The role of the super-type is to easily inherit some instances. E.g. if the super-type is SingleListBox () then we will inherit instances for Items, Selection, and Selecting. The role of the user-type is to let the composite-widget programmer instantiate arbitrary classes. We will see the use of super-type in the first example, and the user of user-type in the second example.

List-box example

We will create a composite widget containing a list and a button to delete elements in the list. The button should only be enabled when some element is selected in the list.

First, the code for the list-box widget:

type MyList = Composite (SingleListBox ()) ()

-- List with delete button
myList :: Window w -> [Prop MyList] -> IO MyList
myList = compose $ \p ->
    do ls <- singleListBox p [ ]
       b  <- button p [ text := "Delete item"
                      , on command := do s <- get ls selection
                                         when (s /= (-1)) (itemDelete ls s)
                      , enabled := False
                      ]
       set ls [ on mouse := \_ -> do s <- get ls selection
                                     set b [ enabled := (s /= (-1)) ]
                                     putStrLn "Mouse event"
                                     propagateEvent
              ]
       return (row 10 [ widget ls, widget b ], ls, ())

as can be seen this code resembles ordinary wxHaskell code, except for the compose function. Thus, it should be easy for the wxHaskell application programmer to get started. Next the code to use our new widget:

main :: IO ()
main = start $
       do w <- frame []

          -- here we use the new MyList widget
          ls <- myList w [ text := "My list", items := map show [1..7], fontSize := 18
                         , on select := print "Some item selected..."
                         ]
          enableB   <- button w [ text := "Outer enable"
                                , on command := do set ls [ enabled := True ] ]
          disableB  <- button w [ text := "Outer disable"
                                , on command := do set ls [ enabled := False ] ]

          set w [ layout := row 10 [ widget ls, widget enableB, widget disableB ] ]

the main function creates a MyList and two buttons which can enable and disable the widget. Again this resembles ordinary wxHaskell code. The reader should note, that we do the right thing with respect to enabledness. If we hit the enable-button MyList’s delete button is only enabled if some item is selected. That is, the widget do not just blindly enable all of it’s child widgets.

Integer entry

This example will create a text entry specialised for integer values. This time we will not inherit the instances of a super-type but implement our own.

-- Text entry for integers

type IntEntry = Composite () (IO Int, Int -> IO ())

intEntry :: Window w -> [Prop IntEntry] -> IO IntEntry
intEntry = compose $ \p ->
    do intEn <- textEntry p [ processEnter := True
                            , on anyKey := handleInput
                            , text := "0"
                            ]
       let getter = do val <- get intEn text
                       readIO val
           setter x = set intEn [ text := show x ]
       return (widget intEn, (), (getter, setter))
    where
      handleInput (KeyChar c) =
          do if c `elem` ['0'..'9']
                then propagateEvent
                else return ()
      handleInput _ = propagateEvent

class IntValue a where
    intValue :: Attr a Int

instance IntValue IntEntry where
    intValue = newAttr "Int attribute" getter setter
        where getter composite = fst (pickUser composite)
              setter composite = snd (pickUser composite)

as can be seen we made a new class for integer valued widgets. Our new composite widget implements this type.

Here is the full code for IntEntry.

Inherited instances

Regardless of using a super-type or not these instances:

  • Widget
  • Able
  • Bordered
  • Child
  • Dimensions
  • Identity
  • Literate
  • Visible
  • Reactive (event class)

are always inherited. This also means that we cannot specialise these instances for a particular widget. But behavior for these classes should be similar for all widgets. Thus, there is no need to specialise them.

If the super-type implements any of:

  • Items
  • Selection
  • Selections
  • Textual
  • Commanding (event class)
  • Selecting (event class)

then so will the composite widget.

Those it is possible to automatically inherit most of the ordinary wxHaskell instances.

Goals

The two examples show that we fulfil goal one though three, as the code resembles ordinary wxHaskell code, is fairly easy to use, and do not involve unsafe code.

Implementation of compose

We use a Composite type to contain the widgets. It is defined as follows:

data Composite super user =
    Composite { pickPanel :: Panel ()
              , pickSuper :: super
              , pickUser  :: user
              }

All of wxHaskell’s widgets are of type ‘forall w. Window w’, but the Composite type is not. However, this is not problematic, as the Composite type will still look like an ordinary wxHaskell widget to the application programmer, due to implementing most of the ordinary wxHaskell type classes.

The most interesting piece is properly the compose function:

compose :: (Panel () -> IO (Layout, super, user))
        -> Window w -> [Prop (Composite super user)] -> IO (Composite super user)
compose f w props =
    do p <- panel w []
       (lay, super, user) <- f p
       set p [ layout := container p lay  ]
       let composite = Composite p super user
       set composite props
       return composite

it simply creates a panel, sets the layout of the panel, and sets all properties. One should note that no properties are set at widget creation time. This may be problematic for functions like fullRepaintOnResize that requires to be set at creation time.

And now we can instantiate the ordinary Haskell classes:

-- Inherit from Panel () - all composites will inherit these classes
instance Widget (Composite super user) where
    widget w = widget (pickPanel w)

instance Able (Composite super user) where
    enabled = mapFromPanel enabled

...

-- Inherit from super
instance Checkable super => Checkable (Composite super user) where
    checkable = mapFromSuper checkable
    checked   = mapFromSuper checked

...

We have not shown all the instantiated classes. However, these can be found at the accompanying source code.

The complete implementation (with comments) is 208 lines, where most of it is boilerplate class instantiations. While I would like it shorter, it is not overly long and the structure is fairly simple.

Conclusion

As shown the proposal lives up to the goals stated in the beginning:

  1. the composite should behave like an ordinary widget to the eyes of the application programmer
  2. be safe to use
  3. be easy to use
  4. simple implementation

One problem with this proposal is that a small number of wxHaskell functions must be called at widget creation time. We might be able to alleviate this with type-safe casts. But this will have to wait for a future posts.

Another issue could be that Composite is not of type ‘forall w. Window w’. However, I do not see any real problem with this, but would very much like comments from people who do.

Feel free to discuss this proposal. Any improvements, critique, questions, or other comments will be most welcome.

Follow

Get every new post delivered to your Inbox.