Haskell从Array转换为Unboxed Array会破坏重写规则

时间:2012-02-11 22:19:02

标签: arrays haskell rules unboxing

我正在尝试将我的程序从使用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时会中断?

2 个答案:

答案 0 :(得分:3)

问题是Data.Array.Unboxed重新导出Data.Array.IArray,因此不可变数组接口的IArray类,但Data.Array没有(它甚至没有)导入它)。因此,如果您使用boundsaccumArrayarray等仅导入Data.Array的函数,则它们在数组类型中是单态的,因此不会产生歧义(多态性在元素类型显然不会在这里造成问题,它会使用合适的类型约束)。但是如果导入Data.Array.Unboxed,则所有这些函数都会产生IArray a e约束,因此重写可能涉及不同的数组类型,从而中断。您需要使用类型签名,函数或规则来修复类型。如何解决这个问题我不能不看代码。

注意:类型检查已更改为7.4,使用ghc-7.4.1,如果导入Data.Array.Unboxed,则没有规则的代码在没有类型签名的情况下无法编译。

要修复类型,以便规则不会产生歧义,您必须提供类型签名

  • 位于顶层,applyWindow
  • 指向paddedImagefilteredPaddedImage的两个本地绑定。

可能需要且最合理的是所有涉及的数组具有相同的类型,可以是

  1. 一个单变型,比如UArray (Int,Int) Int(元素类型也可以是Word,...)
  2. 数组类型中的单形单元和元素类型中的多态
  3. 两种类型的ploymorphic
  4. 对于1.,您只需添加签名applyWindow :: T -> T -> TxxImage :: T(其中T是所需类型)。对于2.,您必须添加两个语言扩展程序FlexibleContextsScopedTypeVariables,然后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才能将元素类型纳入范围,以便paddedImagefilteredPaddedImage可以获得类型签名。对于3.,只需要ScopedTypeVariablesapplyWindow的类型签名将是

    applyWindow :: forall a e. (Num e, IArray a e) => ...
    

    强制所有数组使用相同类型的另一种方法是使用asTypeOf或将它们全部放入列表(未使用的本地绑定),但最好使用IMO类型签名。

    一旦修复了所有类型(它们不一定必须相同,但本地绑定的类型必须由参数和结果类型确定,可能仅由参数类型确定),规则应该键入check。 (可能还需要修复indexMult中的类型。)

答案 1 :(得分:2)

当我尝试运行this code没有数组的显式类型签名(在这种情况下为UArray Int Bool)时,我收到了完全相同的错误消息(关于IArray等),只是{{} 1}}导入。当我添加签名时,一切都还可以。也许这对你也有帮助。