Haskell 跟踪约束的技术
下面是一个场景:我编写了一些带有类型签名的代码,GHC投诉无法推断某些Haskell 跟踪约束的技术,haskell,constraints,ghc,Haskell,Constraints,Ghc,下面是一个场景:我编写了一些带有类型签名的代码,GHC投诉无法推断某些x和y的x~y。通常,您可以抛出GHC骨骼,然后简单地将同构添加到函数约束中,但这是一个坏主意,原因如下: 它并不强调理解代码 您可以在一个约束已经足够的情况下得到5个约束(例如,如果5个约束由一个更具体的约束暗示) 如果你做错了什么,或者GHC无济于事,你最终可能会受到虚假的约束 我刚刚花了几个小时和第三个案子作斗争。我正在玩,我试图定义一个独立于域的共享版本,类似于中定义的版本 我有这个: {-# LANGUAGE GAD
x
和y
的x~y。通常,您可以抛出GHC骨骼,然后简单地将同构添加到函数约束中,但这是一个坏主意,原因如下:
共享版本
,类似于中定义的版本
我有这个:
{-# 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
{-#语言GADT、灵活上下文、类型运算符#-}
导入数据。语法
--基于纳米长石
数据泄露到哪里
Let::Let(a:->(a->b):->完全b)
共享:(让:(a->b)->b)fi)
=>a->(a->b)->a
分享
而GHC无法推断(内部a)~(内部b)
,这肯定不是我想要的。所以要么我写了一些我不想写的代码(这需要约束),要么GHC因为我写的一些其他约束而想要那个约束
事实证明我需要将(语法a,语法b,语法(a->b))
添加到约束列表中,所有这些都不意味着(内部a)~(内部b)
。我基本上偶然发现了正确的约束条件;我仍然没有一个系统的方法来找到它们
我的问题是:
内部a~b
,那么GHC从哪里得到的呢首先,你的函数有错误的类型;我很确定它应该是(没有上下文)
a->(a->b)->b
。GHC7.10在指出这一点上更有帮助,因为对于原始代码,它抱怨缺少约束
内部(a->b)~(内部a->内部a)
。在确定了共享的类型之后,GHC 7.10仍然有助于指导我们:
无法推断(内部(a->b)~(内部a->内部b))
无法推断(sup~域(a->b))
无法推断(语法a)
,无法推断(语法b)
和无法推断(语法a->b))
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
share::(Let:b)~sup,
内部(a->b)~(内部a->内部b),
句法a,句法b,句法(a->b),
语法(a->(a->b)->b)fi)
=>a->(a->b)->b
分享
至于您关于跟踪GHC从何处获得其约束要求的问题,您可以尝试,特别是,
-ddump tc trace
,然后阅读生成的日志,查看将内部(a->b)~t
和(内部a->内部a)~t
添加到通缉集中的位置,但这将是一个相当长的阅读过程。您在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
share::(让:(a->b)->b)fi,
_)
=>a->(a->b)->a
分享
关键是在约束中使用类型洞:\u=>您的困难类型
关于类型级调试器有一些讨论,但普遍的共识似乎表明,typechecker的内部逻辑不会有任何帮助:/Haskell的约束求解器是一种蹩脚的不透明逻辑语言:)@jozefg你有讨论的链接吗?通常只需完全删除类型签名,让ghci告诉你它对签名的看法就可以了应该是。不知何故,a
和b
是绑定的-在上下文之外查看类型签名-a->(a->b)->a
,而不是a->(a->b)->b
。也许就是这样?使用约束解算器,它们可以在任何地方影响传递等式,但错误通常显示出一个位置“靠近”约束被诱导的位置。尽管@jozefg-可能会用标签或其他东西来注释约束,以显示它们来自何处,但这还是很酷的:s