假设我有以下功能:
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/