可以使用函数的附加类型限制声明Functor实例

时间:2015-10-19 20:37:09

标签: frege

我正在努力将GHC / Arr.hs移植到弗雷格。

定义了数组:

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的重新绑定的仿函数吗?

1 个答案:

答案 0 :(得分:3)

不,这是不可能的。

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

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

请注意,类型安全java数组存在另一个问题。假设我们想要创建一个Double数组(但是同一个参数适用于任何其他元素类型)。 AFAIK,Haskell要求Arrays元素必须是懒惰的。因此,我们实际上不能使用java类型double[]JArray Double将成为弗雷格对应物)来对其进行建模。因为,如果我们这样做,每个数组元素一旦设置就必须进行评估。

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

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))}

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

此外,AElem的构造和AElem s作为实际数组元素的使用对实际值施加严格性。

毋庸置疑,Array模块的用户不应(需要)了解这些实现细节,即AElem类型。