haskell - Techniques for Tracing Constraints

ID : 9189

viewed : 179

Tags : haskellconstraintsghchaskell

Top 5 Answer for haskell - Techniques for Tracing Constraints

vote vote


First of all, your function has the wrong type; I am pretty sure it should be (without the context) a -> (a -> b) -> b. GHC 7.10 is somewhat more helpful in pointing that out, because with your original code, it complains about a missing constraint Internal (a -> b) ~ (Internal a -> Internal a). After fixing share's type, GHC 7.10 remains helpful in guiding us:

  1. Could not deduce (Internal (a -> b) ~ (Internal a -> Internal b))

  2. After adding the above, we get Could not deduce (sup ~ Domain (a -> b))

  3. After adding that, we get Could not deduce (Syntactic a), Could not deduce (Syntactic b) and Could not deduce (Syntactic (a -> b))

  4. After adding these three, it finally typechecks; so we end up with

    share :: (Let :<: sup,           Domain a ~ sup,           Domain b ~ sup,           Domain (a -> b) ~ sup,           Internal (a -> b) ~ (Internal a -> Internal b),           Syntactic a, Syntactic b, Syntactic (a -> b),           SyntacticN (a -> (a -> b) -> b) fi)       => a -> (a -> b) -> b share = sugarSym Let 

So I'd say GHC hasn't been useless in leading us.

As for your question about tracing where GHC gets its constraint requirements from, you could try GHC's debugging flags, in particular, -ddump-tc-trace, and then read through the resulting log to see where Internal (a -> b) ~ t and (Internal a -> Internal a) ~ t are added to the Wanted set, but that will be quite a long read.

vote vote


Did you try this in GHC 8.8+?

share :: (Let :<: sup,           Domain a ~ sup,           Domain b ~ sup,           SyntacticN (a -> (a -> b) -> b) fi,           _)        => a -> (a -> b) -> a share = sugarSym Let 

The key is to use type hole among constraints: _ => your difficult type

vote vote


A contentious point perhaps, but instead of setting the culture to en-US, you can set it to Invariant. In the Invariant culture, the error messages are in English.

Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture; Thread.CurrentThread.CurrentUICulture = CultureInfo.InvariantCulture; 

It has the advantage of not looking biased, especially for non-American English speaking locales. (a.k.a. avoids snide remarks from colleagues)

vote vote


Here is solution that does not require any coding and works even for texts of exceptions that are loaded too early for us to be able to change by code (for example, those in mscorlib).

It may not be always applicable in every case (it depends on your setup as you need to be able to create a .config file aside the main .exe file) but that works for me. So, just create an app.config in dev, (or a [myapp].exe.config or web.config in production) that contains the following lines for example:

<configuration>   ...   <runtime>     <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">       <dependentAssembly>         <assemblyIdentity name="mscorlib.resources" publicKeyToken="b77a5c561934e089"                           culture="fr" /> <!-- change this to your language -->          <bindingRedirect oldVersion="" newVersion="999.0.0.0"/>       </dependentAssembly>       <dependentAssembly>         <assemblyIdentity name="System.Xml.resources" publicKeyToken="b77a5c561934e089"                           culture="fr" /> <!-- change this to your language -->          <bindingRedirect oldVersion="" newVersion="999.0.0.0"/>       </dependentAssembly>        <!-- add other assemblies and other languages here -->      </assemblyBinding>   </runtime>   ... </configuration> 

What this does is tell the framework to redirect assembly bindings for mscorlib's resources and System.Xml's resources, for versions between 1 and 999, in french (culture is set to "fr") to an assembly that ... does not exists (an arbitrary version 999).

So when the CLR will look for french resources for these two assemblies (mscorlib and System.xml), it will not find them and fallback to English gracefully. Depending on your context and testings, you might want to add other assemblies to these redirects (assemblies that contains localized resources).

Of course I don't think this is supported by Microsoft, so use at your own risk. Well, in case you detect a problem, you can just remove this configuration and check it's unrelated.

vote vote


Windows needs to have the UI language you want to use installed. It it doesn't, it has no way of magically knowing what the translated message is.

In an en-US windows 7 ultimate, with pt-PT installed, the following code:

Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo("pt-PT"); string msg1 = new DirectoryNotFoundException().Message;  Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo("en-US"); string msg2 = new FileNotFoundException().Message;  Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo("fr-FR"); string msg3 = new FileNotFoundException().Message; 

Produces messages in pt-PT, en-US and en-US. Since there is no French culture files installed, it defaults to the windows default (installed?) language.

Top 3 video Explaining haskell - Techniques for Tracing Constraints