本文翻译自:Techniques for Tracing Constraints
Here's the scenario: I've written some code with a type signature and GHC complains could not deduce x ~ y for some x
and y
. 这是一个场景:我写了一些带有类型签名的代码,GHC抱怨无法推断x
和y
某些x
和y
。 You can usually throw GHC a bone and simply add the isomorphism to the function constraints, but this is a bad idea for several reasons: 你通常可以将GHC作为一个骨骼并简单地将同构函数添加到函数约束中,但这有几个原因:
I just spent several hours battling case 3. I'm playing with syntactic-2.0
, and I was trying to define a domain-independent version of share
, similar to the version defined in NanoFeldspar.hs
. 我只花了几个小时与案例3作斗争。我正在使用syntactic-2.0
,我试图定义一个与域无关的share
版本,类似于NanoFeldspar.hs
定义的版本。
I had this: 我有这个:
{-# LANGUAGE GADTs, FlexibleContexts, TypeOperators #-}
import Data.Syntactic
-- Based on NanoFeldspar.hs
data Let a where
Let :: Let (a :-> (a -> b) :-> Full b)
share :: (Let :<: sup,
Domain a ~ sup,
Domain b ~ sup,
SyntacticN (a -> (a -> b) -> b) fi)
=> a -> (a -> b) -> a
share = sugarSym Let
and GHC could not deduce (Internal a) ~ (Internal b)
, which is certainly not what I was going for. 和GHC could not deduce (Internal a) ~ (Internal b)
,这当然不是我想要的。 So either I had written some code I didn't intend to (which required the constraint), or GHC wanted that constraint due to some other constraints I had written. 所以要么我写了一些我不想要的代码(需要约束),要么GHC想要这个约束,因为我写了一些其他的约束。
It turns out I needed to add (Syntactic a, Syntactic b, Syntactic (a->b))
to the constraint list, none of which imply (Internal a) ~ (Internal b)
. 事实证明我需要将(Syntactic a, Syntactic b, Syntactic (a->b))
到约束列表中,其中没有一个暗示(Internal a) ~ (Internal b)
。 I basically stumbled upon the correct constraints; 我基本上偶然发现了正确的限制; I still don't have a systematic way to find them. 我仍然没有系统的方法来找到它们。
My questions are: 我的问题是:
Internal a ~ Internal b
, so where did GHC pull that from? 语法中没有任何内容有一个约束Internal a ~ Internal b
,那么GHC从哪里拉出来? 参考:https://stackoom.com/question/1aNvy/追踪约束的技巧
First of all, your function has the wrong type; 首先,你的函数有错误的类型; I am pretty sure it should be (without the context) a -> (a -> b) -> b
. 我很确定它应该是(没有上下文) 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)
. GHC 7.10在指出这一点时更有帮助,因为使用原始代码,它会抱怨缺少约束Internal (a -> b) ~ (Internal a -> Internal a)
。 After fixing share
's type, GHC 7.10 remains helpful in guiding us: 在确定share
类型后,GHC 7.10仍然有助于指导我们:
Could not deduce (Internal (a -> b) ~ (Internal a -> Internal b))
After adding the above, we get Could not deduce (sup ~ Domain (a -> b))
添加上述内容后,我们得到Could not deduce (sup ~ Domain (a -> b))
After adding that, we get Could not deduce (Syntactic a)
, Could not deduce (Syntactic b)
and Could not deduce (Syntactic (a -> b))
添加之后,我们得到Could not deduce (Syntactic a)
, Could not deduce (Syntactic b)
和Could not deduce (Syntactic (a -> b))
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. 所以我说GHC在领导我们方面毫无用处。
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. 至于关于追踪GHC获取其约束要求的问题,您可以尝试GHC的调试标志 ,特别是-ddump-tc-trace
,然后读取结果日志以查看Internal (a -> b) ~ t
-ddump-tc-trace
和(Internal a -> Internal a) ~ t
被添加到Wanted
集,但这将是相当长的阅读。