[Haskell-cafe] Trapped by the Monads

robert dockins robdockins at fastmail.fm
Tue Sep 20 11:33:51 EDT 2005

Mark Carter wrote:
> I'm puzzling out how to get a Bool from am IO Bool. I know I'm not 
> supposed to, but I don't see any way around my predicament.
> The basic setup is: I have an edit box, and a panel. If you click the 
> LMB on the panel when the edit box is checked, this means you want to 
> move a graphical object around the panel. If it is unchecked, then 
> clicking the LMB means you want to add a graphical object.
> The relevant bits I've managed to put together so far are:
> mainFrame = do -- main application frame
>    streams <- varCreate []
>   ...
>    cbEdit <- checkBox p1 [text := "Edit Mode",  on command ::=  onCbEdit 
> textlog] -- p1 is the panel, ignore textlog
>    let isEditing =  get cbEdit checked -- returns type IO Bool
>    windowOnMouse p False {- no motion events -} (onMouse p streams  
> isEditing)
>   ...
>  where
>    onMouse w streams isEditChecked mouse              = case mouse of
>            MouseLeftDown pt mods  ->
>                if isEditChecked then
>                    findStream w streams pt
>                else
>                    addStream w streams pt
>            other                  -> skipCurrentEvent      -- 
> unprocessed event: send up the window chain
>        where
>             -- define findStream and addStream
> The problem is that isEditChecked is of type IO Bool, not Bool. I 
> presume that I should actually be taking a different (non-imperative) 
> approach, and I'm wondering if anyone could suggest what that approach 
> should be? Many apologies for being a clueless n00b.

Well, your onMouse function is acutally in the IO monad, so you can just 
use the do notation.  You can also get rid of the case, like so:

  onMouse w streams isEditChecked (MouseLeftDown pt mods) =
               do ec <- isEditChecked
                  if ec then ... else ...

  onMouse _ _ _ _ = skipCurrentEvent

More information about the Haskell-Cafe mailing list