Использование newtype в данных.Массив.Распаковано с ghc 7.10
Это прекрасно работало в 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 об этом не упоминается, я вижу https://ghc.haskell.org/trac/ghc/ticket/9220#comment:11 допускает свое разрушительное изменение. Но каково решение – действительно ли мне нужно создать оболочку newtype для MyArr с вспомогательными функциями для каждого использования?
1 ответ:
Вам не нужно создавать оболочку для
MyArr
, но вам придется вручную выписать экземпляр, который вы ранее получили. Немного грубое силовое решение-этоunsafeCoerce
Ваш путь через экземплярIArray
вручную (причина, по которой вы не можетеcoerce
, та же, что вы не можете вывести).{-# 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)