模糊类型变量

时间:2009-12-08 07:51:00

标签: haskell generic-programming

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下,由于上述错误,该程序无法编译。

2 个答案:

答案 0 :(得分:9)

您似乎需要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纳入范围。

答案 1 :(得分:0)

l在函数replace中的类型应相同: 将其定义为:

data L = LInt Integer| LString String

请参阅,replace不能是多态函数。它使用严格的类型。这种类型由操作定义:

Prelude> :t (+)
(+) :: (Num a) => a -> a -> a

Prelude> :t (:)
(:) :: a -> [a] -> [a]

Prelude> :t 'c'
'c' :: Char

要使替换多态,你必须使其具有多态函数。