I continue experimenting with Haskell and GUI https://github.com/bigos/cairo-example/blob/1c4448a936031b0e5b66b77027be975d040df01b/src/Main.hs and I've ran into another problem.
I have two identical functions with different result type:
getWidgetSize :: Gtk.DrawingArea -> Render (Int, Int)
getWidgetSize widget = do
width' <- fromIntegral <$> Gtk.widgetGetAllocatedWidth widget
height' <- fromIntegral <$> Gtk.widgetGetAllocatedHeight widget
return (width', height')
getWidgetSize2 :: Gtk.DrawingArea -> IO (Int, Int)
getWidgetSize2 widget = do
width' <- fromIntegral <$> Gtk.widgetGetAllocatedWidth widget
height' <- fromIntegral <$> Gtk.widgetGetAllocatedHeight widget
return (width', height')
One is used in this function
updateCanvas :: Gtk.DrawingArea -> Model -> Render ()
and the other is used in the main function.
Is it possible to remove the code duplication?
Following Vora's advice I have used the following:
getWidgetSize :: Gtk.DrawingArea -> IO (Int, Int)
getWidgetSize widget = do
width' <- fromIntegral <$> Gtk.widgetGetAllocatedWidth widget
height' <- fromIntegral <$> Gtk.widgetGetAllocatedHeight widget
return (width', height')
updateCanvas :: Gtk.DrawingArea -> Model -> Render ()
updateCanvas canvas model = do
size <- liftIO (getWidgetSize canvas)
Easiest way would be to use the fact that Render
is a MonadIO
, meaning you could simply make one IO
typed definition, and liftIO
the call when inside the Render
Monad.
Edit:
As per Carl's suggestion, and since widgetGetAllocatedWidth
/widgetGetAllocatedHeight
are constrained on the MonadIO
requisite, you could also make a
getWidgetSize :: MonadIO m => Gtk.DrawingArea -> m (Int, Int)
getWidgetSize widget = do
width' <- liftIO $ fromIntegral <$> Gtk.widgetGetAllocatedWidth widget
height' <- liftIO $ fromIntegral <$> Gtk.widgetGetAllocatedHeight widget
return (width', height')
which would then work in both scenario. This is mostly equivalent, however it allows it to be called the same way from any MonadIO
context.
Edit2: (Because more edits is always better right guys)
Edit3: Because sometimes you look at something from too close, and you miss it.
The liftIO
, which I moved inside the do
block for clarity, can also be removed to declutter the field a bit :
getWidgetSize :: MonadIO m => Gtk.DrawingArea -> m (Int, Int)
getWidgetSize widget = do
width' <- fromIntegral <$> Gtk.widgetGetAllocatedWidth widget
height' <- fromIntegral <$> Gtk.widgetGetAllocatedHeight widget
return (width', height')
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With