2016-12-05 76 views
3

這個工作在GHC 7.8.4罰款,但未能在7.10.3:NEWTYPE與GHC 7.10

{-# 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承認其突破性的變化。但是,解決方案是什麼 - 我是否真的必須爲MyArr創建一個新類型的包裝器,併爲每種用法使用輔助函數?

+0

有趣。也許'UArray'從元素的表現轉化爲名義角色?我想知道爲什麼。 – chi

+1

是的,看起來像你會(另一個'vector'的參數 - 獲得'UnBox'實例更容易)。即使你想通過'IArray UArray Elt'實例'unsafeCoerce',你也不能導出你需要實現的方法。雖然我明白爲什麼我們不應該在這裏接地,但我們無法手寫我們的'IArray'實例的事實讓我有點不高興...... – Alec

+1

您可以從'Data.Array.Base'中導入方法。 –

回答

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)