我试图用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)我为每个函数设置了类型,但没有解决问题。
你知道这种类型的歧义从何而来,以及如何消除它?
发布于 2015-04-01 13:43:25
快速解决办法:
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字段是我们可能获得关于defaultSettings的m参数的信息的唯一来源,并且完全不受约束,所以GHC不能推断m是MonadIO。
如果我们添加(defaultSettings :: Settings IO),那么旧的m参数将被实例化为IO,不再有问题了。请注意,新的m参数与旧的m参数完全无关,因为我们只是忽略了旧的complete字段,并将其替换为新函数。通过顶级m注释,新的mySettings :: Settings IO参数被确定为IO。
实际上,我们可以用任何defaultSettings类型实例化MonadIO,结果都是一样的。同样,这是因为我们忽略了complete的旧值。
发布于 2015-04-01 15:16:20
Settings的类型有点多态。注意,haskeline作者意识到了这个可能的问题,并提供了一个 function来避免这个特定的问题。如其他答案所示,手动指定类型也是一个选项。
https://stackoverflow.com/questions/29390884
复制相似问题