开发者

Ambiguous type variable

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 o开发者_StackOverflow社区f 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.


It looks like you need the scoped type variables extension.

{-# LANGUAGE ScopedTypeVariables #-}

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

Note that quantification must be explicit to bring l into scope.


l should be of same type in function replace: Define it like:

data L = LInt Integer| LString String

See, replace can't be a polymorphic function. It uses strict types. This types defined by operations:

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

and

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

and

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

To make replace polymorphic you have to make it of polymorphic functions.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜