我正在尝试使用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)
我为每个函数设置了类型,但它没有解决问题.
你知道这种模糊性来自何处以及如何删除它?
快速修复:
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.
现在,问题Settings是m参数仅出现在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.
| 归档时间: |
|
| 查看次数: |
81 次 |
| 最近记录: |