我正在尝试使用非常通用的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))
我想做什么才有意义?
提前致谢!
答案 0 :(得分:5)
我们需要重复您将要使用的数组方法的约束,例如array
等。由于您的索引是固定的,我们知道它们是Ix
的实例,我们只需要添加IArray
约束:
myFunction :: (IArray UArray a, IArray UArray b)
=> a -> b -> ((UArray Int a), (UArray Int b))
为此,您需要FlexibleContexts(请参阅 7.6.3.2。实例上下文的轻松规则)语言扩展。
您还可以考虑将函数概括为任意数组(而不仅仅是UArray
s
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))
(对于这两个变体,您不需要扩展名。)
由于您可能正在使用UArray
来提高速度,因此我建议添加INLINE
pragma,以便针对您使用它的地方的特定数据类型优化您的函数。这可以显着提高速度。