不明确的类型变量

发布于 2024-08-14 07:16:39 字数 1424 浏览 7 评论 0原文

与我之前关于遍历数据结构的问题相关,我'当我将代码与 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

此代码在最后两行上都会产生以下错误:

约束中的类型变量“l”不明确:
  Test.hs:31:10-52 中使用“transformBi”产生的“数据 l”
可能的修复:添加修复这些类型变量的类型签名

我可以明白为什么这段代码不明确: transformBi 接受 (to -> to)from 并将其转换为 来自;就我而言,Child1 l 中的 lParent l 中的 l 之间没有链接。我不知道如何解决它。我尝试添加类似 transformBi (doInt :: Child1 l -> Child1 l) 的类型约束,但出现相同的错误;当我这样做时,就好像我正在引入一个新的l

如何告诉编译器我对 replacetransformBi doInttransformBi doString 使用相同的 l

编辑: 这是演示我正在做的事情的完整程序。在GHC 6.10.4下,该程序无法编译,并出现上述错误。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

碍人泪离人颜 2024-08-21 07:16:39

看起来您需要

{-# 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纳入范围。

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.

荒路情人 2024-08-21 07:16:39

l 在函数 replace 中应该具有相同的类型:
定义如下:

data L = LInt Integer| LString String

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

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

and

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

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

要使替换多态,您必须将其设为多态函数。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文