我正在尝试将我的程序从使用Data.Array转换为Data.Array.Unboxed。
快速侧面说明: 有几个地方说我可以改变" Array"到" UArray"在我的代码中 并添加Data.Array.Unboxed的导入,但我不是两者兼而有之 这样的数组类型 我刚刚导入Data.Array.Unboxed而不是Data.Array,这是否足够?
当我进行切换时,以下重写规则会中断:
{-# RULES
"applyWindow/applyWindow" forall win1 win2 image.
applyWindow win1
(applyWindow win2
image) =
applyWindow (indexMult win1 win2)
image
#-}
这里win1 win2和image应该都是UArrays。但是,由于以下错误,无法编译。
FIPlib/Core.hs:229:99:
Ambiguous type variables `e0', `a0' in the constraint:
(IArray a0 e0) arising from a use of `applyWindow'
Probable fix: add a type signature that fixes these type variable(s)
In the expression: applyWindow (indexMult win1 win2) image
When checking the transformation rule "applyWindow/applyWindow"
FIPlib/Core.hs:229:99:
Ambiguous type variables `e0', `a2' in the constraint:
(IArray a2 e0) arising from a use of `applyWindow'
Probable fix: add a type signature that fixes these type variable(s)
In the expression: applyWindow (indexMult win1 win2) image
When checking the transformation rule "applyWindow/applyWindow"
FIPlib/Core.hs:229:112:
Ambiguous type variables `e0', `a1' in the constraint:
(IArray a1 e0) arising from a use of `indexMult'
Probable fix: add a type signature that fixes these type variable(s)
In the first argument of `applyWindow', namely
`(indexMult win1 win2)'
In the expression: applyWindow (indexMult win1 win2) image
When checking the transformation rule "applyWindow/applyWindow"
是什么让这个含糊不清?为什么在使用Data.Array时会中断?
答案 0 :(得分:3)
问题是Data.Array.Unboxed
重新导出Data.Array.IArray
,因此不可变数组接口的IArray
类,但Data.Array
没有(它甚至没有)导入它)。因此,如果您使用bounds
,accumArray
,array
等仅导入Data.Array
的函数,则它们在数组类型中是单态的,因此不会产生歧义(多态性在元素类型显然不会在这里造成问题,它会使用合适的类型约束)。但是如果导入Data.Array.Unboxed
,则所有这些函数都会产生IArray a e
约束,因此重写可能涉及不同的数组类型,从而中断。您需要使用类型签名,函数或规则来修复类型。如何解决这个问题我不能不看代码。
注意:类型检查已更改为7.4,使用ghc-7.4.1,如果导入Data.Array.Unboxed
,则没有规则的代码在没有类型签名的情况下无法编译。
要修复类型,以便规则不会产生歧义,您必须提供类型签名
applyWindow
,paddedImage
和filteredPaddedImage
的两个本地绑定。可能需要且最合理的是所有涉及的数组具有相同的类型,可以是
UArray (Int,Int) Int
(元素类型也可以是Word
,...)对于1.,您只需添加签名applyWindow :: T -> T -> T
和xxImage :: T
(其中T
是所需类型)。对于2.,您必须添加两个语言扩展程序FlexibleContexts
和ScopedTypeVariables
,然后applyWindow
将获得签名
applyWindow :: forall e. (Num e, IArray UArray e)
=> UArray (Int,Int) e -> UArray (Int,Int) e -> UArray (Int,Int) e
并且本地绑定将获得签名xxImage :: UArray (Int,Int) e
。需要FlexibleContexts
才能在constarint中出现UArray
,并且必须ScopedTypeVariables
才能将元素类型纳入范围,以便paddedImage
和filteredPaddedImage
可以获得类型签名。对于3.,只需要ScopedTypeVariables
,applyWindow
的类型签名将是
applyWindow :: forall a e. (Num e, IArray a e) => ...
强制所有数组使用相同类型的另一种方法是使用asTypeOf
或将它们全部放入列表(未使用的本地绑定),但最好使用IMO类型签名。
一旦修复了所有类型(它们不一定必须相同,但本地绑定的类型必须由参数和结果类型确定,可能仅由参数类型确定),规则应该键入check。 (可能还需要修复indexMult
中的类型。)
答案 1 :(得分:2)
当我尝试运行this code没有数组的显式类型签名(在这种情况下为UArray Int Bool
)时,我收到了完全相同的错误消息(关于IArray等),只是{{} 1}}导入。当我添加签名时,一切都还可以。也许这对你也有帮助。