[Haskell-beginners] Problem in Gtk2Hs/Glade

Daniel Fischer daniel.is.fischer at web.de
Mon Oct 11 13:48:22 EDT 2010


On Monday 11 October 2010 18:19:24, Tom Hobbs wrote:
> Hi all,
>
> I playing around with simple cell automaton (Conway's Game Of Life).
> I've got working code which prints everything out nicely to the
> terminal, I'm trying to wrap everything in a nice GUI using Glade and
> Gtk2Hs.
>
> In order to create my world, I have a function defined as;
>
> makeWorld :: Int -> [(Int,Int)]
>
> Which accepts an Int, representing the size of the world, then then
> outs the world itself - note the world is always assumed to be square.
>  The list contains pairs such that the first element of the pair is
> the index (such as for an array) and the second is the value at that
> position.  For right or wrong, that's how my (working) Game Of Life
> has been implemented.  The problem comes in the Gtk2Hs code...
>
> main = do
>   initGUI
>   Just xml <- xmlNew "gameOfLife.glade"
>   window <- xmlGetWidget xml castToWindow "mainWindow"
>   onDestroy window mainQuit
>   quitButton <- xmlGetWidget xml castToButton "quitButton"
>   onClicked quitButton $ do
>     widgetDestroy window
>   setWorldSize <- xmlGetWidget xml castToButton "setWorldSize"
>   sizeBox <- xmlGetWidget xml castToEntry "worldSize"
>   onClicked setWorldSize $ do
>     canvas <- xmlGetWidget xml castToDrawingArea "world"
>     let size = (read (get sizeBox entryText) :: Int)
>     cellworld <- makeWorld size
>     printWorld cellworld
>   widgetShowAll window
>   mainGUI
>
> The above function does not compile under GHC because;
>
> gameOfLife.hs:27:20:
> Couldn't match expected type `String'
> against inferred type `IO String'
> In the first argument of `read', namely `(get sizeBox entryText)'
> In the expression: (read (get sizeBox entryText) :: Int)
> In the definition of `size':
> size = (read (get sizeBox entryText) :: Int)

get sizeBox entryText

is an IO-action which, when executed gets the entry-text from sizeBox.
The type is IO String.
What you want is the entry-text, hence the result of the IO-action, so you 
have to run that action and bind its result to a name, for example

    text <- get sizeBox entryText
    let size = read text

or, on one line

    size <- fmap read (get sizeBox entryText)

>
> gameOfLife.hs:28:2:
> Couldn't match expected type `[(Int, Int)]'
> against inferred type `IO (Int, Int)'
> In a stmt of a 'do' expression: cellworld <- makeWorld size
> In the second argument of `($)', namely
> `do { canvas <- xmlGetWidget xml castToDrawingArea "world";
> let size = (read (get sizeBox entryText) :: Int);
> cellworld <- makeWorld size;
> printWorld cellworld }'
> In a stmt of a 'do' expression:
> onClicked setWorldSize
> $ do { canvas <- xmlGetWidget xml castToDrawingArea "world";
> let size = (read (get sizeBox entryText) :: Int);
> cellworld <- makeWorld size;
> printWorld cellworld }

makeWorld size, on the other hand is not an IO-action but a list (of 
(Int,Int) pairs), so you can't use "<-" to bind it to a name in an IO-
block, here you must use let:

    let cellworld = makeWorld size
    print cellWorld

>
> It seems to be complaining about the call to my makeWorld function,
> although I do not understand why that should be.  The line number
> which GHC complains about does correspond to the "cellworld <-
> makeWorld size" line in my main function.
>
> I've not yet worked out how to draw my world in the GUI, the
> "printWorld" function mentioned above just spills the world out to the
> termainal for now.
>
> Does anyone have any ideas?
>
> Many thanks,
>
> Tom



More information about the Beginners mailing list