gpt4 book ai didi

haskell - 如何确定 ghc 为什么要寻找特定类型的类实例?

转载 作者:行者123 更新时间:2023-12-03 12:18:53 25 4
gpt4 key购买 nike

当条件类型类实例深入运行时,可能很难弄清楚为什么 ghc 提示缺少类型类实例。例如:

class MyClass1 c
class MyClass2 c
class MyClass3 c

data MyType1 a
data MyType2 a

instance MyClass1 a => MyClass2 (MyType1 a)
instance MyClass2 a => MyClass3 (MyType2 a)

foo :: (MyClass3 c) => c
foo = undefined

bar :: MyType2 (MyType1 Int)
bar = foo

GHC 给出以下错误:
Example.hs:149:7-9: error:
• No instance for (MyClass1 Int) arising from a use of ‘foo’
• In the expression: foo
In an equation for ‘bar’: bar = foo
|
149 | bar = foo
| ^^^

假设我只写了 foo 的定义和 bar ,而其他所有内容都是我没有编写的导入代码,我可能对 ghc 为何试图找到 MyClass1 感到非常困惑。 Int 的实例.这甚至可能是我第一次听说 MyClass1。类,如果到目前为止我一直依赖于导入的实例。如果 ghc 能给我一个类型类实例链的“堆栈跟踪”,那就太好了,例如
Sought (MyClass2 (MyType1 Int)) to satisfy (MyClass3 (MyType2 (MyType1 Int))) from conditional type class instance OtherModule.hs:37:1-18
Sought (MyClass1 Int) to satisfy (MyClass2 (MyType1 Int)) from conditional type class instance OtherModule.hs:36:1-18

ghc 是否为此提供了命令行选项?如果没有,我该如何调试?

请记住,我的真正问题比这个简单的例子要复杂得多。例如
Search.hs:110:31-36: error:
• Could not deduce (Ord
(Vars (DedupingMap (Rep (Index gc)) (IndexedProblem ac))))
arising from a use of ‘search’
from the context: (PP gc (IndexedProblem ac),
Show (Vars (DedupingMap (Rep (Index gc)) (IndexedProblem ac))),
Foldable f, MonadNotify m)
bound by the type signature for:
searchIndexedReplicaProblem :: forall gc ac (f :: * -> *) (m :: *
-> *).
(PP gc (IndexedProblem ac),
Show
(Vars
(DedupingMap
(Rep (Index gc)) (IndexedProblem ac))),
Foldable f, MonadNotify m) =>
f (Index
(Clzs
(PartitionedProblem
gc (IndexedProblem ac))))
-> m (Maybe
(Vars
(PartitionedProblem
gc (IndexedProblem ac))))
at Search.hs:(103,1)-(109,131)
• In the expression: search
In an equation for ‘searchIndexedReplicaProblem’:
searchIndexedReplicaProblem = search
|
110 | searchIndexedReplicaProblem = search
| ^^^^^^

PP 有五个覆盖条件,我使用的是类型族和不可判定的实例,所以 ghc 给我错误的原因非常不明显。我可以使用哪些工具来追踪问题?

最佳答案

你可以试试-ddump-cs-trace选项,虽然它旨在帮助 GHC 开发人员在调试约束解决代码时,但它也可能对您有用。这是您的示例的输出:

Step 1[l:2,d:0] Kept as inert:
[G] $dMyClass3_a1rt {0}:: MyClass3 c_a1rs[sk:2]
Step 2[l:2,d:0] Dict equal (keep):
[WD] $dMyClass3_a1rv {0}:: MyClass3 c_a1rs[sk:2]
Constraint solver steps = 2
Step 1[l:1,d:0] Top react: Dict/Top (solved wanted):
[WD] $dMyClass3_a2uc {0}:: MyClass3 (MyType2 (MyType1 Int))
Step 2[l:1,d:1] Top react: Dict/Top (solved wanted):
[WD] $dMyClass2_a2up {1}:: MyClass2 (MyType1 Int)
Step 3[l:1,d:2] Kept as inert:
[WD] $dMyClass1_a2uq {2}:: MyClass1 Int
Step 4[l:2,d:0] Kept as inert:
[G] $dMyClass3_a1rB {0}:: MyClass3 c_a1rz[sk:2]
Step 5[l:2,d:0] Wanted CallStack IP:
[WD] $dIP_a2u8 {0}:: ?callStack::GHC.Stack.Types.CallStack
Step 6[l:2,d:0] Kept as inert:
[WD] $dIP_a2uA {0}:: ?callStack::GHC.Stack.Types.CallStack
Step 7[l:2,d:0] Kept as inert:
[G] $dMyClass2_a2uh {0}:: MyClass2 a_a2ug[ssk:2]
Step 8[l:2,d:0] Kept as inert:
[G] $dMyClass1_a2ul {0}:: MyClass1 a_a2uk[ssk:2]
Constraint solver steps = 8

从这个转储中提取有用的信息并不容易,但 AFAIK 它是目前唯一可用的选项。少数相关票证: 13443 , 15044

添加:
我将尝试解释一下转储的含义。我实际上并不熟悉 GHC 内部,所以这只是我(可能是错误的)理解。

相关位是下一个:
Step 1[l:1,d:0] Top react: Dict/Top (solved wanted):
[WD] $dMyClass3_a2uc {0}:: MyClass3 (MyType2 (MyType1 Int))
Step 2[l:1,d:1] Top react: Dict/Top (solved wanted):
[WD] $dMyClass2_a2up {1}:: MyClass2 (MyType1 Int)
Step 3[l:1,d:2] Kept as inert:
[WD] $dMyClass1_a2uq {2}:: MyClass1 Int

这里 d代表“深度”, WD是“想要的派生”约束。所以我们有类似想要的约束的堆栈跟踪:最初我们想要 MyClass3 (MyType2 (MyType1 Int)) ,然后我们找到了 MyClass3 MyType2 的实例, 现在我们想要 MyClass2 (MyType1 Int)来满足它。然后我们找到了 MyClass2 MyType1 的实例, 现在我们想要 MyClass1 Int来满足它。我知道,解释很模糊,但我只有这些,对不起。

关于haskell - 如何确定 ghc 为什么要寻找特定类型的类实例?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50826535/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com