我继续尝试 Haskell 和 GUI https://github.com/bigos/cairo-example/blob/1c4448a936031b0e5b66b77027be975d040df01b/src/Main.hs 我遇到了另一个问题。
我有两个相同的函数,但结果类型不同:
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')
此函数中使用了一个
updateCanvas :: Gtk.DrawingArea -> Model -> Render ()
另一个在main函数中使用。
是否可以删除重复的代码?
解决方案
按照 Vora 的建议,我使用了以下内容:
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)
最佳答案
最简单的方法是利用 Render
是一个 MonadIO
这一事实,这意味着您可以简单地创建一个 IO
类型定义,并且 liftIO
在 Render
Monad 内进行的调用。
编辑:
根据 Carl 的建议,由于 widgetGetAllocationWidth
/widgetGetAllocationHeight
受到 MonadIO
必需条件的限制,您还可以制作
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')
这将在这两种情况下工作。这基本上是等效的,但是它允许从任何 MonadIO
上下文中以相同的方式调用它。
编辑2:(因为更多的编辑总是更好,对的人)
Edit3:因为有时你看某样东西太近了,你就会错过它。
为了清晰起见,我将 liftIO
移到了 do
block 内,也可以将其删除以稍微整理字段:
getWidgetSize :: MonadIO m => Gtk.DrawingArea -> m (Int, Int)
getWidgetSize widget = do
width' <- fromIntegral <$> Gtk.widgetGetAllocatedWidth widget
height' <- fromIntegral <$> Gtk.widgetGetAllocatedHeight widget
return (width', height')
关于haskell - 如何删除两个具有不同输出类型的相同 Haskell 函数中的重复代码?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50240956/