Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Broken code with roles in GHC 7.8

Tags:

haskell

ghc

Some of my code is broken with the newest version of ghc 7.8.2.

I'm using GeneralizedNewtypeDeriving to deriving instances of Data.Vector.Unbox using the following:

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)

where VoxelPos have manual rolled instances using (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) ...
  ...

and this was working with the previous versions of ghc. But after upgrading ghc, I get the following error:

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)

which, I think, is because of addition of roles. I know that roles improves safety when using GeneralizedNewtypeDeriving which is, of course, really good!

What are the possible solutions to solve this? And what is the most recommended one?

like image 529
LambdaStaal Avatar asked Apr 15 '14 06:04

LambdaStaal


Video Answer


1 Answers

Having an error here is sensible -- it's possible that the U.MVector instance for FacePos is utterly unrelated to the instance for VoxelPos. There's a nice way to fix this, though:

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

That should get rid of the particular error you're seeing.

However, I think you'll hit another role-related error right away, because other functions (not basicLength, where you're snagged) use the MVector parameters in a way roles can't currently deal with.

The GHC team is aware of this problem and is working on it: see https://ghc.haskell.org/trac/ghc/ticket/9112 and https://ghc.haskell.org/trac/ghc/ticket/9123

In the meantime, I'm afraid my only suggestion is to use unsafeCoerce. :(

like image 88
Richard Eisenberg Avatar answered Sep 23 '22 13:09

Richard Eisenberg