Сломанный код с ролями в GHC 7.8

Некоторые из моего кода разбиты на самую новую версию ghc 7.8.2.

Я использую GeneralizedNewtypeDeriving для вывода экземпляров Data.Vector.Unbox, используя следующее:

data VoxelPos     = VoxelPos
                    {-# UNPACK #-} !Int
                    {-# UNPACK #-} !Int
                    {-# UNPACK #-} !Int
                  deriving (Show, Eq, Ord)

newtype FacePos = FacePos VoxelPos deriving ( Eq, Hashable, NFData, G.Vector U.Vector, M.MVector U.MVector, U.Unbox)

где VoxelPos имеют ручные свернутые экземпляры с использованием (Int, Int, Int):

newtype instance U.MVector s VoxelPos = MV_VoxelPos (U.MVector s (Int, Int, Int))
newtype instance U.Vector    VoxelPos = V_VoxelPos  (U.Vector    (Int, Int, Int))
instance U.Unbox VoxelPos
instance M.MVector U.MVector VoxelPos where
  basicLength (MV_VoxelPos v) ...
  ...

и это работало с предыдущими версиями ghc. Но после обновления ghc я получаю следующую ошибку:

Could not coerce from ‘U.MVector s (Int, Int, Int)’ to ‘U.MVector
                                                              s FacePos’
      because the second type argument of ‘U.MVector’ has role Nominal,
      but the arguments ‘(Int, Int, Int)’ and ‘FacePos’ differ
      arising from the coercion of the method ‘M.basicLength’ from type
                   ‘forall s. U.MVector s VoxelPos -> Int’ to type
                   ‘forall s. U.MVector s FacePos -> Int’
    Possible fix:
      use a standalone 'deriving instance' declaration,
        so you can specify the instance context yourself
    When deriving the instance for (M.MVector U.MVector FacePos)

который, я думаю, связан с добавлением ролей. Я знаю, что роли улучшают безопасность при использовании GeneralizedNewtypeDeriving, который, конечно, действительно хорош!

Каковы возможные решения для решения этой проблемы? И что является самым рекомендуемым?

Ответ 1

Наличие ошибки здесь разумно - возможно, что экземпляр U.MVector для FacePos совершенно не связан с экземпляром для VoxelPos. Там хороший способ исправить это:

newtype instance U.MVector s FacePos = MV_FacePos (U.MVector s VoxelPos)

Это должно избавиться от конкретной ошибки, которую вы видите.

Однако я думаю, что вы сразу же ударите другую связанную с ролью ошибку, потому что другие функции (а не basicLength, где вы зацепили) используют параметры MVector таким образом, чтобы роли в настоящее время не обрабатываются.

Команда GHC знает об этой проблеме и работает над ней: см. https://ghc.haskell.org/trac/ghc/ticket/9112 и https://ghc.haskell.org/trac/ghc/ticket/9123

Тем временем, я боюсь, что мое единственное предложение - использовать unsafeCoerce.: (