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

时间:2015-04-01 12:28:34

标签: 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"

但我对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)

我为每个功能设置了类型,但它没有解决问题。

您是否知道此类歧义来自何处以及如何将其删除?

2 个答案:

答案 0 :(得分:6)

快速修复:

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

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

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

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

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

事实上,我们可以使用任何defaultSettings类型实例化MonadIO,结果将是相同的。同样,这是因为我们忽略了complete的旧值。

答案 1 :(得分:3)

Settings的类型有点太多态。请注意, haskeline 作者了解了这个可能的问题,并提供了a setComplete function来避免此特定问题。手动指定类型也是一个选项,因为其他答案显示。