以下是场景:我编写了一些带有类型签名的代码,而GHC抱怨无法推断某些x
和y
的x~y。你通常可以将GHC作为一个骨骼并简单地将同构函数添加到函数约束中,但出于以下几个原因这是一个坏主意:
我只花了几个小时与案例3作斗争。我正在玩syntactic-2.0
,我正在尝试定义与share
无关的域版本,类似于{{3}中定义的版本}}
我有这个:
{-# 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)
。我基本上偶然发现了正确的限制;我仍然没有系统的方法来找到它们。
我的问题是:
Internal a ~ Internal b
,那么GHC从哪里拉出来?答案 0 :(得分:5)
首先,你的函数类型错误;我很确定它应该是(没有上下文)a -> (a -> b) -> b
。 GHC 7.10在指出这一点时更有帮助,因为使用原始代码,它会抱怨缺少约束
Internal (a -> b) ~ (Internal a -> Internal a)
。在确定share
类型之后,GHC 7.10仍然有助于指导我们:
Could not deduce (Internal (a -> b) ~ (Internal a -> Internal b))
添加上述内容后,我们会获得Could not deduce (sup ~ Domain (a -> b))
添加后,我们得到Could not deduce (Syntactic a)
,Could not deduce (Syntactic b)
和Could not deduce (Syntactic (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
所以我说GHC在领导我们方面毫无用处。
关于跟踪GHC获取约束要求的问题,您可以尝试GHC's debugging flags,尤其是-ddump-tc-trace
,然后阅读生成的日志以查看Internal (a -> b) ~ t
的位置并且(Internal a -> Internal a) ~ t
被添加到Wanted
集,但这将是一个很长的阅读。
答案 1 :(得分:0)
您在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
关键是在约束中使用类型孔:_ => your difficult type