haskell - 如何删除两个具有不同输出类型的相同 Haskell 函数中的重复代码?

标签 haskell

我继续尝试 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 类型定义,并且 liftIORender 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/

相关文章:

haskell - `Except` 的复杂性在 Haskell 中有何用途?

haskell - 反射(reflection) Haskell 中函数的输入?

haskell - 查找列表中元素的索引

haskell - 使用索引数组索引 Data.Vector

haskell - Haskell 中的 Monoid Bool

haskell - 一个棘手的haskell问题

python - Haskell 在朴素整数分解中比 Python 慢?

haskell - 通过++ 或 <> 进行字符串连接

Haskell 数据类型列表

haskell - 就 pure 和 liftA2 而言,应用仿函数定律是什么?