Сломанный код с ролями в 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
.: (