Home > front end >  How can I use GeneralizedNewTypeDeriving to derive Vector and MVector?
How can I use GeneralizedNewTypeDeriving to derive Vector and MVector?

Time:01-17

Near the top of the haddocks for Data.Vector.Unboxed, there is a discussion of how to use GeneralizedNewTypeDeriving to derive instances of Vector and MVector. The following example, edited to use LANGUAGE pragmas, is stated:

{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE TypeFamilies #-}

import qualified Data.Vector.Generic as G
import qualified Data.Vector.Generic.Mutable as M
import qualified Data.Vector.Unboxed as U

newtype Foo = Foo Int

newtype instance U.MVector s Foo = MV_Int (U.MVector s Int)
newtype instance U.Vector Foo = V_Int (U.Vector Int)
deriving instance M.MVector U.MVector Foo
deriving instance G.Vector U.Vector Foo
instance U.Unbox Foo

However, it does not type check, failing with a long message that begins

• Couldn't match representation of type: m Int
                           with that of: m Foo
    arising from a use of ‘GHC.Prim.coerce’
  NB: We cannot know what roles the parameters to ‘m’ have;
    we must assume that the role is nominal
• In the expression:
    GHC.Prim.coerce
      @(U.MVector (Control.Monad.Primitive.PrimState m) Int
        -> Int -> m Int)
      @(U.MVector (Control.Monad.Primitive.PrimState m) Foo
        -> Int -> m Foo)
      (M.basicUnsafeRead @U.MVector @Int)
  In an equation for ‘M.basicUnsafeRead’:
      M.basicUnsafeRead
        = GHC.Prim.coerce
            @(U.MVector (Control.Monad.Primitive.PrimState m) Int
              -> Int -> m Int)
            @(U.MVector (Control.Monad.Primitive.PrimState m) Foo
              -> Int -> m Foo)
            (M.basicUnsafeRead @U.MVector @Int)

The example is somehow wrong or lacking, but I'm at a loss as to how to fix it.

I'll note that I can get this working quite easily with Data.Vector.Unboxed.Deriving (or by writing everything out manually):

derivingUnbox
  "Foo"
  [t|Foo -> Int|]
  [|\(Foo i) -> i|]
  [|Foo|]

My understanding of GeneralizedNewTypeDeriving is that it avoids the trivial application and removal of the constructor that I have to do in the above, so I'd like to be able to use it here if possible.

EDIT: Per request, I am using stack resolver lts-19.33, which is at ghc-9.0.2.

CodePudding user response:

Recently, vector version 0.13.0.0 got a change that allows deriving using GeneralizedNewtypeDeriving with its classes (changelog). Indeed, before that, this just wasn't possible. Since you are using vector version 0.12.3.1 (via lts-19.33), the solution is to upgrade to the latest version.

  • Related