haskell - 单子(monad)绑定(bind)的显式签名约束

标签 haskell types type-constraints

假设我有以下功能:

loadDialog :: String -> IO MyDialog
loadDialog file = do
  Just ui <- xmlNew file
  MyDialog
    <$> xmlGetWidget ui castToWindow "w"
    <*> xmlGetWidget ui castToButton "b"

在哪里

xmlGetWidget :: WidgetClass widget => GladeXML -> (GObject -> widget) -> String -> IO widget

现在我想捕捉以下 xmlNew/xmlGetWidget 使用模式:

widgetBinder :: WidgetClass widget => FilePath -> IO ((GObject -> widget) -> String -> IO widget)
widgetBinder file = do
  Just ui <- xmlNew file
  return $ xmlGetWidget ui

这应该允许我写:

loadDialog file = do
  bind <- widgetBinder file
  MyDialog
    <$> bind castToWindow "w"
    <*> bind castToButton "b"

问题是,它不进行类型检查(确切错误 here )。我认为可以显式地为绑定(bind)提供通用签名,但似乎单子(monad)绑定(bind)不是这种情况,因为以下内容也没有进行类型检查(即使使用 RankNTypes,错误 here):

loadDialog file = do
  bind :: WidgetClass w => (GObject -> w) -> String -> IO w
       <- widgetBinder file
  MyDialog
    <$> bind castToWindow "w"
    <*> bind castToButton "b"

有什么我可以做的吗?

最佳答案

一个笨拙但可行的解决方案是将您的函数放入新类型:

newtype Binder = Binder (forall w. WidgetClass w => (GObject -> w) -> String -> IO w)

widgetBinder :: FilePath -> IO Binder
widgetBinder file = do
  Just ui <- xmlNew file
  return $ Binder (xmlGetWidget ui)

loadDialog file = do
  Binder bind <- widgetBinder file
  MyDialog
    <$> bind castToWindow "w"
    <*> bind castToButton "b"

或者类似的东西......

关于haskell - 单子(monad)绑定(bind)的显式签名约束,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20803484/

相关文章:

c# - 为什么 Nullable<T> 被视为结构而不是类?

haskell - applicative 到底有多重要,而不是 "combining"?

haskell - 无法生成 hoogle 数据,因为 wget 证书已过期?

python - Yaml 通过 Camel 序列化 : using base class load/dump and accessing type(self) in decorator

generics - 类型级编程中的协变

Java AST 解析器 - 获取参数的完整类型、外部项目

函数 (+) (-) (/) (*) 的 Haskell 模式匹配

haskell - 什么是协变仿函数?

haskell - 循环素数

rust - 关联类型的相等性约束的替代方法