3

我正在将 GHC/Arr.hs 移植到 Frege 中。

数组定义:

data Array i e = Array{u,l::i,n::Int,elems::(JArray e)}

有功能:

amap :: (Ix i, ArrayElem e) => (a -> b) -> Array i a -> Array i b

现在,我不知道如何Functor为它定义实例,因为

instance (Ix i) => Functor (Array i) where
    fmap = amap

但是编译器抱怨推断类型比预期的更受限制,这似乎是真的。我可以为函数制作Array一个带有限制的函子ArrayElem -> ArrayElem吗?

4

1 回答 1

3

不,这是不可能的。

如果您Array基于JArray并想要一个仿函数实例,则不得使用任何产生 ArrayElem(或任何其他附加)上下文的函数。

另一种说法是,您不能Array基于类型安全的 java 数组,而必须处理 type 的 java 数组Object[]。因为,正如您毫无疑问地指出的那样,ArrayElem类型类只是能够在创建 java 数组时提供正确的 java 类型的技巧。当然,这对于与 Java 的接口和性能原因很重要。

请注意,类型安全的 java 数组还有另一个问题。假设我们想要创建一个数组Double(但相同的参数适用于任何其他元素类型)。AFAIK,Haskell 要求 Arrays 元素必须是惰性的。因此,我们真的不能使用 java 类型double[]JArray Double与 Frege 对应的类型)对其进行建模。因为,如果我们这样做,每个数组元素都必须在设置后立即进行评估。

出于这个原因,我建议你使用一些通用的自定义数组元素类型,比如

data AElem a = AE () a 
mkAE = A () 
unAE (AE _ x) = x
derive ArrayElement AElem

并更改您的定义:

data Array i e = Array{u,l::i,n::Int,elems::(JArray (AElem e))}

现在,您的仿函数实例可以编写,因为不会出现 ArrayElem 约束,因为当您访问elems数组时,编译器知道您有AElem元素并且可以并且将提供正确的实例。

此外,s 的构造AElem和将AElems 用作实际数组元素不会实际值施加严格限制。

不用说,Array 模块的用户不应该(不需要)知道那些实现细节,也就是AElem类型。

于 2015-10-20T17:48:19.867 回答