1

我正在尝试使用非常通用的 UArrays 编写一个函数。我想要类型签名:

myFunction :: a -> b -> ((UArray Int a), (UArray Int b))

但是,a 和 b 太笼统了。我希望它们成为可能的实例之一IArray UArray a。是否有一些派生类型可以让我指定这个?例如,如果 Num 是一个有效的实例,我可以这样做:

myFunction :: (Num a, Num b) => a -> b -> ((UArray Int a), (UArray Int b))

我想做的事情有意义吗?

提前致谢!

4

1 回答 1

5

我们需要从您将要使用的数组方法中重复约束,例如arrayetc。由于您的索引是固定的并且我们知道它们是 的实例Ix,我们只需要添加IArray约束:

myFunction :: (IArray UArray a, IArray UArray b)
           => a -> b -> ((UArray Int a), (UArray Int b))

为此,您需要FlexibleContexts(参见第7.6.3.2 节。实例上下文的宽松规则)语言扩展。

您还可以考虑将您的函数推广到任意数组(不仅仅是UArrays

myFunction1 :: (IArray arr a, IArray arr b)
            => a -> b -> ((arr Int a), (arr Int b))

甚至可能是任意索引:

myFunction2 :: (IArray arr a, IArray arr b, Ix i)
            => a -> b -> ((arr i a), (arr i b))

(对于这 2 个变体,您不需要扩展。)

由于您可能正在使用UArrays 来提高速度,因此我建议添加INLINEpragma 以便您的函数在您使用它的地方针对特定数据类型进行优化。这可以显着提高速度。

于 2013-01-29T23:35:36.823 回答