Haskeline auto-complete ambiguous type variable

I am trying to implement an autocomplete function using 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" 

but I'm a little disappointed with this GHC error:

 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) 

I set a type for each function, but this did not solve the problem.

Do you have an idea where this type ambiguity comes from and how to remove it?

+5
source share
2 answers

Quick fix:

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

The problem is a very rare boundary case, so it is not surprising that the above solution may seem arbitrary or incomprehensible. However, I am trying to explain this.

defaultSettings is of type MonadIO m => Settings m . This is a polymorphic value, and such values ​​often cause hiccups in type inference. As a rule, we can perform calculations (pattern matching, field forecasts, etc.) using polymorphic values ​​if the GHC can infer a polymorphic parameter from the context. Settings m may have completely different content depending on the exact m and the exact class methods of the class that belong to m .

Now the problem with Settings is that the parameter m is only present in the complete field, which is of type CompletionFunc m . But in our example, we ignore the old complete field and simply replace it with the new field. Therefore, as far as GHC knows, the old complete field could be of any type. And since the old complete field is the only source from which we could get information about the m defaultSettings parameter, and we left it completely without restrictions, the GHC cannot conclude that m is MonadIO .

If we add (defaultSettings :: Settings IO) , then the old m parameter will be created in IO , and there are no more problems. Note that the new parameter m is not completely associated with the old parameter m , because we simply ignored the old complete field and replaced it with a new function. The new m parameter is defined as an IO top-level annotation mySettings :: Settings IO .

In fact, we can create an instance of defaultSettings with any type of MonadIO , and the result will be the same. Again, this is because we are ignoring the old complete value.

+6
source

The Settings type is a little too polymorphic. Please note that the haskeline authors were aware of this possible problem and provided a setComplete function to avoid this specific problem. Manually specifying a type is also an option, as other answers show.

+3
source

Source: https://habr.com/ru/post/1216602/


All Articles