my earlier question on traversing data structures相关,将代码与uniplate软件包一起使用时,我在使代码通用时遇到问题。我正在处理Language.Exts.Annotated.Syntax模块中的数据结构,这些数据结构都是通用的,带有类型参数l。在整个树中,此l相同。

我正在编写的代码是这样的:

doInt :: Child1 l -> Child1 l
doInt (Child1 l n) = Child1 l (n + 1)

doString :: Child2 l -> Child2 l
doString (Child2 l (_:s)) = Child2 l ('j' : s)

replace :: Data l => Parent l -> Parent l
replace = transformBi doInt
        . transformBi doString


此代码在后两行均产生以下错误:


Ambiguous type variable `l' in the constraint:
  `Data l' arising from a use of `transformBi' at Test.hs:31:10-52
Probable fix: add a type signature that fixes these type variable(s)



我可以看到为什么这段代码是模棱两可的:transformBi接受(to -> to)from并将其转换为from;就我而言,在l中的Child1 ll中的Parent l之间没有链接。我看不到如何解决它。我尝试添加transformBi (doInt :: Child1 l -> Child1 l)之类的类型约束,但遇到相同的错误;好像在执行此操作时要引入一个新的l

如何告诉编译器我对lreplacetransformBi doInt使用相同的transformBi doString

编辑:Here is the full program that demonstrates what I'm doing。在GHC 6.10.4下,该程序无法编译,出现上述错误。

最佳答案

看来您需要scoped type variables扩展名。

{-# LANGUAGE ScopedTypeVariables #-}

replace :: forall l. Data l => Parent l -> Parent l
replace = transformBi (doInt :: Child1 l -> Child1 l)
        . transformBi (doString :: Child2 l -> Child2 l)


注意,量化必须明确,才能将l纳入范围。

10-08 13:01