Haskeline自动完成的模糊类型变量

Jea*_*ouX 5 haskell haskeline

我正在尝试使用Haskeline实现自动完成功能:

import System.Console.Haskeline
import System.Console.Haskeline.IO
import Data.List

mySettings :: Settings IO
mySettings = defaultSettings {
                                historyFile = Just "myhist"
                              , complete = completeWord Nothing " \t" $ return . search
                              }

keywords :: [String]
keywords = ["Point","Line","Circle","Sphere"]

search :: String -> [Completion]
search str = map simpleCompletion $ filter (str `isPrefixOf`) keywords

main :: IO ()
main = do
        inputLine <- initializeInput mySettings
        putStrLn "done"
Run Code Online (Sandbox Code Playgroud)

但我对这个GHC错误感到有点失望:

Ambiguous type variable `t0' in the constraint:
  (Control.Monad.IO.Class.MonadIO t0)
    arising from a use of `defaultSettings'
Probable fix: add a type signature that fixes these type variable(s)
Run Code Online (Sandbox Code Playgroud)

我为每个函数设置了类型,但它没有解决问题.

你知道这种模糊性来自何处以及如何删除它?

And*_*ács 6

快速修复:

mySettings :: Settings IO
mySettings = (defaultSettings :: Settings IO)
  {  historyFile = Just "myhist"
   , complete    = completeWord Nothing " \t" $ return . search } 
Run Code Online (Sandbox Code Playgroud)

问题是一个非常罕见的极端情况,所以难怪上述解决方案似乎是任意或不可理解的.不过我试着解释一下.

defaultSettings有类型MonadIO m => Settings m.它是一个多态值,这样的值通常会导致类型推断出现打嗝.通常,如果GHC可以从上下文推断出多态参数,我们只能对多态值进行计算(模式匹配,字段投影等).Settings m可能具有完全不同的内容,具体取决于m所属的确切类型类方法m.

现在,问题Settingsm参数仅出现在complete具有类型的字段中CompletionFunc m.但在我们的示例中,我们忽略complete字段,只需将其替换为新字段即可.因此,就GHC而言,旧complete场可以是任何类型的.而且由于旧complete场是我们可能获得有关m参数的信息的唯一来源defaultSettings,并且我们完全不受约束,GHC无法推断出那m是一个MonadIO.

如果我们添加(defaultSettings :: Settings IO),那么旧m参数将被实例化,IO并且不再存在问题.请注意, m参数与旧m参数完全无关,因为我们只是忽略旧complete字段并将其替换为新函数.新m参数IO由顶级mySettings :: Settings IO注释确定.

实际上,我们可以defaultSettings用任何MonadIO类型进行实例化,结果也是一样的.再次,这是因为我们忽略了旧的价值complete.