这是一种情况:我已经编写了一些带有类型签名的代码,GHC抱怨无法为x x
和y推导某些代码y
。通常,您可以将GHC扔掉,然后将同构添加到功能约束中,但这是一个坏主意,原因有以下几个:
- 它不强调理解代码。
- 您最终可以得到5个约束,而其中一个约束就足够了(例如,如果5个约束被一个更具体的约束隐含)
- 如果您做错了某事或GHC无助,您可能会受到虚假约束的限制
我只花了几个小时与案例3进行斗争。我正在玩syntactic-2.0
,并且试图定义一个与域无关的版本share
,类似于中定义的版本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 could not deduce (Internal a) ~ (Internal b)
,这当然不是我想要的。因此,要么我写了一些我不想写的代码(需要约束),要么GHC由于我写的其他一些约束而想要那个约束。
事实证明,我需要添加(Syntactic a, Syntactic b, Syntactic (a->b))
到约束列表,但都没有暗示(Internal a) ~ (Internal b)
。我基本上偶然发现了正确的约束;我仍然没有系统的方法来找到它们。
我的问题是:
- GHC为什么提出这一限制?句法上没有任何约束
Internal a ~ Internal b
,那么GHC是从哪里提取约束的呢? - 通常,可以使用哪些技术来追踪GHC认为需要的约束的起源?即使对于我可以发现自己的约束,我的方法本质上还是通过物理地写下递归约束来强行逼迫违规路径。这种方法基本上是在无穷无尽的约束条件下进行的,是我所能想到的效率最低的方法。
a
,b
被绑定-在上下文之外查看类型签名- a -> (a -> b) -> a
而不是a -> (a -> b) -> b
。也许就是这样吗?使用约束求解器,它们可以在任何地方影响传递等式,但是错误通常会显示一个位置,该位置“接近”诱导约束的位置。@jozefg太酷了-也许用标签或其他东西注释约束,以显示约束的来源?:s