haskell – 技术跟踪约束

这里的情况:我写了一些类型签名的代码,GHC抱怨不能推导出x〜y的某些x和y。你通常可以抛出GHC一个骨头,只是添加同构到函数约束,但这是一个坏主意,有几个原因:

>它不强调理解代码。
>你可以结束5个约束,其中一个已经足够(例如,如果5由一个更具体的约束隐含)
>如果你做错了事或者如果GHC没有帮助,你可能会被伪造的约束

我只花了几个小时与案例3战斗。我在玩syntactic-2.0,我试图定义一个独立于域的版本的共享,类似于NanoFeldspar.hs中定义的版本。

我有这个:

{-# 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

和GHC不能推断(内部a)〜(内部b),这肯定不是我要去的。所以,我写了一些代码我不打算(这需要约束),或GHC想要的约束,由于一些其他约束我写了。

结果我需要添加(语法a,语法b,语法(a-> b))到约束列表,其中没有一个暗示(内部a)〜(内部b)。我基本上偶然遇到正确的约束;我还没有系统的方法来找到它们。

我的问题是:

> GHC为什么提出这个约束?句法中没有地方有一个约束内部a〜内部b,那么GHC从哪里得到?
>一般来说,什么技术可以用来追踪GHC认为需要的约束的起源?即使对于我可以发现自己的约束,我的方法本质上是通过物理写下递归约束的暴力强迫违规的路径。这种方法基本上是一个无限的兔子洞约束,是关于我可以想象的最低效的方法。

首先,你的函数有错误的类型;我很肯定应该是(没有上下文)a – > (a→b)→ b。 GHC 7.10在指出这一点有点更有帮助,因为与你的原始代码,它抱怨缺少约束
内部(a→b)〜(内部a→内部a)。在确定股份类型后,GHC 7.10仍然有助于指导我们:

>无法推导(Internal(a→b)〜(Internal a – > Internal b))
>添加上述内容后,我们得到无法推导(sup〜Domain(a→b))
>添加后,我们得到无法推导(语法a),无法推导(语法b)和无法推导(语法(a – > b))
>添加这三个后,它终于typechecks;所以我们最终得到了

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

所以我想说GHC没有没有用来带领我们。

对于跟踪GHC从哪里获得其约束要求的问题,您可以尝试GHC’s debugging flags,特别是-ddump-tc-trace,然后读取生成的日志以查看Internal(a→b)〜t和(内部a – >内部a)〜t被添加到期望集合,但是这将是相当长的读。

翻译自:https://stackoverflow.com/questions/23448150/techniques-for-tracing-constraints

转载注明原文:haskell – 技术跟踪约束