Related to my earlier question on traversing data structures, I'm having a problem making my code generic when I use it along with the uniplate package. I'm dealing with the data structures in the Language.Exts.Annotated.Syntax module, which are all generic with a type parameter l
. This l
is the same throughout the tree.
The kind of code I'm writing is like this:
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
This code produces the following error on both of the last two lines:
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)
I can see why this code is ambiguous: transformBi
accepts a (to -> to)
and from
and turns it into a from
; in my case there's no link between the l
in Child1 l
and the l
in Parent l
. What I don't see is how to fix it. I've tried adding a type constraint like transformBi (doInt :: Child1 l -> Child1 l)
, but I get the same error; it's as if I'm introducing a new l
when I do this.
How can I tell the compiler that I'm using the same l
for replace
, transformBi doInt
and transformBi doString
?
Edit: Here is the full program that demonstrates what I'm doing. Under GHC 6.10.4, this program fails to compile, with the above error.