Использование newtype в Data.Array.Unboxed с 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 допускает серьезные изменения. Но каково решение - действительно ли мне нужно создавать упаковщик нового типа для 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) 
Другие вопросы по тегам