Haskell 在Data.Array.unbox中使用新类型与ghc 7.10

Haskell 在Data.Array.unbox中使用新类型与ghc 7.10,haskell,types,coercion,Haskell,Types,Coercion,这在ghc 7.8.4中运行良好,但在7.10.3中失败: {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} module Foo where import qualified Data.Array.Unboxed as A import GHC.Generics (Generic) newtype Elt =

这在ghc 7.8.4中运行良好,但在7.10.3中失败:

{-# LANGUAGE DeriveGeneric              #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}

module Foo where

import qualified Data.Array.Unboxed       as A
import           GHC.Generics             (Generic)

newtype Elt = Elt Int deriving (Eq, Ord, Show, Num, Integral, Real, Enum, A.IArray A.UArray, Generic)
type MyArr = A.UArray Int Elt
有很多信息,比如

/tmp/my.hs:9:75:
    Couldn't match type ‘Int’ with ‘Elt’
    arising from the coercion of the method ‘Data.Array.Base.numElements’
      from type ‘forall i. A.Ix i => A.UArray i Int -> Int’
        to type ‘forall i. A.Ix i => A.UArray i Elt -> Int’
    Relevant role signatures:
      type role A.Ix nominal
      type role A.UArray nominal nominal
    When deriving the instance for (A.IArray A.UArray Elt)
虽然7.10的发行说明没有提到这一点,但我明白了
承认这是一个突破性的变化。但是解决方案是什么呢?我真的必须为MyArr创建一个新类型的包装器,在每次使用时都要使用帮助函数吗?

您不必为MyArr创建包装器,但您必须手工写出以前派生的实例。一种蛮力解决方案是手动通过
IArray
实例执行
unsafectoerce
(无法
强制
的原因与无法派生的原因相同)

{-#语言实例集、ScopedTypeVariables、MultiParamTypeClasses}
导入Data.Array.Base
导入Data.Array.IArray
导入Data.Array.unbox
导入不安全。强制
实例IArray UArray Elt在哪里
边界::对我来说。Ix i=>UArray i Elt->(i,i)
bounds arr=bounds(不安全的arr::UArray i Int)
所有的我。Ix i=>UArray i Elt->Int
numElements arr=numElements(未安全的arr::UArray i Int)
雷:对我来说。Ix i=>(i,i)->[(Int,Elt)]->UArray i Elt
unsafarray lu ies=unsafecerce(unsafarray lu[(i,e)|(i,Elt e)UArray i Elt->Int->Elt
unsafeAt arr ix=Elt(unsafeAt(unsafeAt)arr::UArray i Int)ix)

有趣。可能
UArray
从元素的代表角色移动到了名义角色?我想知道为什么。是的,看起来你会这样做(向量
的另一个参数-获取
取消装箱
实例要容易得多)。即使你想通过
IArray UArray Elt
实例
unsafectorce
,你也不能,因为你需要实现的方法没有导出。虽然我理解为什么我们不应该在这里接地,但我们不能手工编写
IArray
的实例这一事实让我有点不高兴……你可以从导入方法e> Data.Array.Base
@ReidBarton噢。出于某种原因,我认为这没有公开。谢谢!@ReidBarton,我认为必要的
强制
应该从
GHC.Arr
Data.Array.Unsafe
或类似的方法导出。这不会给我们GND,但会让我们
强制
方法。
{-# LANGUAGE InstanceSigs, ScopedTypeVariables, MultiParamTypeClasses #-}

import Data.Array.Base
import Data.Array.IArray
import Data.Array.Unboxed
import Unsafe.Coerce

instance IArray UArray Elt where
  bounds :: forall i. Ix i => UArray i Elt -> (i, i)
  bounds arr = bounds (unsafeCoerce arr :: UArray i Int)                                                                                                                                                                        

  numElements :: forall i. Ix i => UArray i Elt -> Int
  numElements arr = numElements (unsafeCoerce arr :: UArray i Int)

  unsafeArray :: forall i. Ix i => (i,i) -> [(Int, Elt)] -> UArray i Elt
  unsafeArray lu ies = unsafeCoerce (unsafeArray lu [ (i,e) | (i,Elt e) <- ies ] :: UArray i Int) :: UArray i Elt

  unsafeAt :: forall i. Ix i => UArray i Elt -> Int -> Elt
  unsafeAt arr ix = Elt (unsafeAt (unsafeCoerce arr :: UArray i Int) ix)