Skip to content

Improve UnboxViaPrim docs - #450

Merged
Shimuuar merged 3 commits into
haskell:masterfrom
sergv:master
Oct 19, 2022
Merged

Shimuuar merged 3 commits into
haskell:masterfrom
sergv:master

Conversation

@sergv

@sergv sergv commented Oct 11, 2022 •

Copy link
Copy Markdown
Contributor

The doctest examples for UnboxViaPrim (https://hackage.haskell.org/package/vector-0.13.0.0/docs/Data-Vector-Unboxed.html#t:UnboxViaPrim) are not self-contained.

When using one of them as-is

#!/usr/bin/env cabal
{- cabal:
build-depends:
  , base
  , vector ^>= 0.13
-}
{-# LANGUAGE DerivingVia                #-}
{-# LANGUAGE GeneralisedNewtypeDeriving #-}
{-# LANGUAGE MultiParamTypeClasses      #-}
{-# LANGUAGE StandaloneDeriving         #-}
{-# LANGUAGE TypeFamilies               #-}

module Main where

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

newtype Foo = Foo Int deriving P.Prim

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

main :: IO ()
main = do
  putStrLn "OK"
  pure ()

I get following error with GHC 9.4

$ cabal run Test.hs

/tmp/test/Test.hs:24:54: error:
    Not in scope: type constructor or class ‘MVector’
    Suggested fix:
      Perhaps use one of these:
        ‘M.MVector’ (imported from Data.Vector.Generic.Mutable),
        ‘U.MVector’ (imported from Data.Vector.Unboxed),
        ‘P.MVector’ (imported from Data.Vector.Primitive)
   |
24 | deriving via (U.UnboxViaPrim Foo) instance M.MVector MVector Foo
   |                                                      ^^^^^^^

/tmp/test/Test.hs:25:54: error:
    Not in scope: type constructor or class ‘Vector’
    Suggested fix:
      Perhaps use one of these:
        ‘G.Vector’ (imported from Data.Vector.Generic),
        ‘U.Vector’ (imported from Data.Vector.Unboxed),
        ‘P.Vector’ (imported from Data.Vector.Primitive)
   |
25 | deriving via (U.UnboxViaPrim Foo) instance G.Vector  Vector  Foo
   |                                                      ^^^^^^

/tmp/test/Test.hs:26:10: error:
    Not in scope: type constructor or class ‘Unbox’
    Suggested fix:
      Perhaps use ‘U.Unbox’ (imported from Data.Vector.Unboxed)
   |
26 | instance Unbox Foo
   |          ^^^^^

After fixing qualified imports I try again with

#!/usr/bin/env cabal
{- cabal:
build-depends:
  , base
  , vector ^>= 0.13
-}
{-# LANGUAGE DerivingVia                #-}
{-# LANGUAGE GeneralisedNewtypeDeriving #-}
{-# LANGUAGE MultiParamTypeClasses      #-}
{-# LANGUAGE StandaloneDeriving         #-}
{-# LANGUAGE TypeFamilies               #-}

module Main where

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

newtype Foo = Foo Int deriving P.Prim

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

main :: IO ()
main = do
  putStrLn "OK"
  pure ()

but now the error is actually interesting and this is what made me create this PR:

$ cabal run Test.hs

/tmp/test/Test.hs:25:1: error:
    • Couldn't match representation of type: P.Vector Foo
                               with that of: U.Vector (U.UnboxViaPrim Foo)
        arising from a use of ‘ghc-prim-0.9.0:GHC.Prim.coerce’
      NB: ‘U.Vector’ is defined in ‘Data.Vector.Unboxed.Base’
          ‘P.Vector’ is defined in ‘Data.Vector.Primitive’
      The data constructor ‘Data.Vector.Unboxed.Base.V_UnboxViaPrim’
        of newtype ‘U.Vector (U.UnboxViaPrim a)’ is not in scope
    • In the expression:
        ghc-prim-0.9.0:GHC.Prim.coerce
          @(G.Mutable U.Vector s (U.UnboxViaPrim Foo)
            -> GHC.ST.ST s (U.Vector (U.UnboxViaPrim Foo)))
          @(G.Mutable U.Vector s Foo -> GHC.ST.ST s (U.Vector Foo))
          (G.basicUnsafeFreeze @U.Vector @(U.UnboxViaPrim Foo))
      In an equation for ‘G.basicUnsafeFreeze’:
          G.basicUnsafeFreeze
            = ghc-prim-0.9.0:GHC.Prim.coerce
                @(G.Mutable U.Vector s (U.UnboxViaPrim Foo)
                  -> GHC.ST.ST s (U.Vector (U.UnboxViaPrim Foo)))
                @(G.Mutable U.Vector s Foo -> GHC.ST.ST s (U.Vector Foo))
                (G.basicUnsafeFreeze @U.Vector @(U.UnboxViaPrim Foo))
      When typechecking the code for ‘G.basicUnsafeFreeze’
        in a derived instance for ‘G.Vector U.Vector Foo’:
        To see the code I am typechecking, use -ddump-deriv
      In the instance declaration for ‘G.Vector U.Vector Foo’
   |
25 | deriving via (U.UnboxViaPrim Foo) instance G.Vector  U.Vector  Foo
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

/tmp/test/Test.hs:25:1: error:
    • Couldn't match representation of type: P.Vector Foo
                               with that of: U.Vector (U.UnboxViaPrim Foo)
        arising from a use of ‘ghc-prim-0.9.0:GHC.Prim.coerce’
      NB: ‘U.Vector’ is defined in ‘Data.Vector.Unboxed.Base’
          ‘P.Vector’ is defined in ‘Data.Vector.Primitive’
      The data constructor ‘Data.Vector.Unboxed.Base.V_UnboxViaPrim’
        of newtype ‘U.Vector (U.UnboxViaPrim a)’ is not in scope
    • In the expression:
        ghc-prim-0.9.0:GHC.Prim.coerce
          @(U.Vector (U.UnboxViaPrim Foo)
            -> GHC.ST.ST s (G.Mutable U.Vector s (U.UnboxViaPrim Foo)))
          @(U.Vector Foo -> GHC.ST.ST s (G.Mutable U.Vector s Foo))
          (G.basicUnsafeThaw @U.Vector @(U.UnboxViaPrim Foo))
      In an equation for ‘G.basicUnsafeThaw’:
          G.basicUnsafeThaw
            = ghc-prim-0.9.0:GHC.Prim.coerce
                @(U.Vector (U.UnboxViaPrim Foo)
                  -> GHC.ST.ST s (G.Mutable U.Vector s (U.UnboxViaPrim Foo)))
                @(U.Vector Foo -> GHC.ST.ST s (G.Mutable U.Vector s Foo))
                (G.basicUnsafeThaw @U.Vector @(U.UnboxViaPrim Foo))
      When typechecking the code for ‘G.basicUnsafeThaw’
        in a derived instance for ‘G.Vector U.Vector Foo’:
        To see the code I am typechecking, use -ddump-deriv
      In the instance declaration for ‘G.Vector U.Vector Foo’
   |
25 | deriving via (U.UnboxViaPrim Foo) instance G.Vector  U.Vector  Foo
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

/tmp/test/Test.hs:25:1: error:
    • Couldn't match representation of type: P.Vector Foo
                               with that of: U.Vector (U.UnboxViaPrim Foo)
        arising from a use of ‘ghc-prim-0.9.0:GHC.Prim.coerce’
      NB: ‘U.Vector’ is defined in ‘Data.Vector.Unboxed.Base’
          ‘P.Vector’ is defined in ‘Data.Vector.Primitive’
      The data constructor ‘Data.Vector.Unboxed.Base.V_UnboxViaPrim’
        of newtype ‘U.Vector (U.UnboxViaPrim a)’ is not in scope
    • In the expression:
        ghc-prim-0.9.0:GHC.Prim.coerce
          @(U.Vector (U.UnboxViaPrim Foo) -> Int) @(U.Vector Foo -> Int)
          (G.basicLength @U.Vector @(U.UnboxViaPrim Foo))
      In an equation for ‘G.basicLength’:
          G.basicLength
            = ghc-prim-0.9.0:GHC.Prim.coerce
                @(U.Vector (U.UnboxViaPrim Foo) -> Int) @(U.Vector Foo -> Int)
                (G.basicLength @U.Vector @(U.UnboxViaPrim Foo))
      When typechecking the code for ‘G.basicLength’
        in a derived instance for ‘G.Vector U.Vector Foo’:
        To see the code I am typechecking, use -ddump-deriv
      In the instance declaration for ‘G.Vector U.Vector Foo’
   |
25 | deriving via (U.UnboxViaPrim Foo) instance G.Vector  U.Vector  Foo
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

/tmp/test/Test.hs:25:1: error:
    • Couldn't match representation of type: P.Vector Foo
                               with that of: U.Vector (U.UnboxViaPrim Foo)
        arising from a use of ‘ghc-prim-0.9.0:GHC.Prim.coerce’
      NB: ‘U.Vector’ is defined in ‘Data.Vector.Unboxed.Base’
          ‘P.Vector’ is defined in ‘Data.Vector.Primitive’
      The data constructor ‘Data.Vector.Unboxed.Base.V_UnboxViaPrim’
        of newtype ‘U.Vector (U.UnboxViaPrim a)’ is not in scope
    • In the expression:
        ghc-prim-0.9.0:GHC.Prim.coerce
          @(Int
            -> Int
            -> U.Vector (U.UnboxViaPrim Foo)
            -> U.Vector (U.UnboxViaPrim Foo))
          @(Int -> Int -> U.Vector Foo -> U.Vector Foo)
          (G.basicUnsafeSlice @U.Vector @(U.UnboxViaPrim Foo))
      In an equation for ‘G.basicUnsafeSlice’:
          G.basicUnsafeSlice
            = ghc-prim-0.9.0:GHC.Prim.coerce
                @(Int
                  -> Int
                  -> U.Vector (U.UnboxViaPrim Foo)
                  -> U.Vector (U.UnboxViaPrim Foo))
                @(Int -> Int -> U.Vector Foo -> U.Vector Foo)
                (G.basicUnsafeSlice @U.Vector @(U.UnboxViaPrim Foo))
      When typechecking the code for ‘G.basicUnsafeSlice’
        in a derived instance for ‘G.Vector U.Vector Foo’:
        To see the code I am typechecking, use -ddump-deriv
      In the instance declaration for ‘G.Vector U.Vector Foo’
   |
25 | deriving via (U.UnboxViaPrim Foo) instance G.Vector  U.Vector  Foo
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

/tmp/test/Test.hs:25:1: error:
    • Couldn't match representation of type: P.Vector Foo
                               with that of: U.Vector (U.UnboxViaPrim Foo)
        arising from a use of ‘ghc-prim-0.9.0:GHC.Prim.coerce’
      NB: ‘U.Vector’ is defined in ‘Data.Vector.Unboxed.Base’
          ‘P.Vector’ is defined in ‘Data.Vector.Primitive’
      The data constructor ‘Data.Vector.Unboxed.Base.V_UnboxViaPrim’
        of newtype ‘U.Vector (U.UnboxViaPrim a)’ is not in scope
    • In the expression:
        ghc-prim-0.9.0:GHC.Prim.coerce
          @(U.Vector (U.UnboxViaPrim Foo)
            -> Int
            -> vector-stream-0.1.0.0:Data.Stream.Monadic.Box
                 (U.UnboxViaPrim Foo))
          @(U.Vector Foo
            -> Int -> vector-stream-0.1.0.0:Data.Stream.Monadic.Box Foo)
          (G.basicUnsafeIndexM @U.Vector @(U.UnboxViaPrim Foo))
      In an equation for ‘G.basicUnsafeIndexM’:
          G.basicUnsafeIndexM
            = ghc-prim-0.9.0:GHC.Prim.coerce
                @(U.Vector (U.UnboxViaPrim Foo)
                  -> Int
                  -> vector-stream-0.1.0.0:Data.Stream.Monadic.Box
                       (U.UnboxViaPrim Foo))
                @(U.Vector Foo
                  -> Int -> vector-stream-0.1.0.0:Data.Stream.Monadic.Box Foo)
                (G.basicUnsafeIndexM @U.Vector @(U.UnboxViaPrim Foo))
      When typechecking the code for ‘G.basicUnsafeIndexM’
        in a derived instance for ‘G.Vector U.Vector Foo’:
        To see the code I am typechecking, use -ddump-deriv
      In the instance declaration for ‘G.Vector U.Vector Foo’
   |
25 | deriving via (U.UnboxViaPrim Foo) instance G.Vector  U.Vector  Foo
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

/tmp/test/Test.hs:25:1: error:
    • Couldn't match representation of type: P.Vector Foo
                               with that of: U.Vector (U.UnboxViaPrim Foo)
        arising from a use of ‘ghc-prim-0.9.0:GHC.Prim.coerce’
      NB: ‘U.Vector’ is defined in ‘Data.Vector.Unboxed.Base’
          ‘P.Vector’ is defined in ‘Data.Vector.Primitive’
      The data constructor ‘Data.Vector.Unboxed.Base.V_UnboxViaPrim’
        of newtype ‘U.Vector (U.UnboxViaPrim a)’ is not in scope
    • In the expression:
        ghc-prim-0.9.0:GHC.Prim.coerce
          @(G.Mutable U.Vector s (U.UnboxViaPrim Foo)
            -> U.Vector (U.UnboxViaPrim Foo) -> GHC.ST.ST s ())
          @(G.Mutable U.Vector s Foo -> U.Vector Foo -> GHC.ST.ST s ())
          (G.basicUnsafeCopy @U.Vector @(U.UnboxViaPrim Foo))
      In an equation for ‘G.basicUnsafeCopy’:
          G.basicUnsafeCopy
            = ghc-prim-0.9.0:GHC.Prim.coerce
                @(G.Mutable U.Vector s (U.UnboxViaPrim Foo)
                  -> U.Vector (U.UnboxViaPrim Foo) -> GHC.ST.ST s ())
                @(G.Mutable U.Vector s Foo -> U.Vector Foo -> GHC.ST.ST s ())
                (G.basicUnsafeCopy @U.Vector @(U.UnboxViaPrim Foo))
      When typechecking the code for ‘G.basicUnsafeCopy’
        in a derived instance for ‘G.Vector U.Vector Foo’:
        To see the code I am typechecking, use -ddump-deriv
      In the instance declaration for ‘G.Vector U.Vector Foo’
   |
25 | deriving via (U.UnboxViaPrim Foo) instance G.Vector  U.Vector  Foo
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

/tmp/test/Test.hs:25:1: error:
    • Couldn't match representation of type: P.Vector Foo
                               with that of: U.Vector (U.UnboxViaPrim Foo)
        arising from a use of ‘ghc-prim-0.9.0:GHC.Prim.coerce’
      NB: ‘U.Vector’ is defined in ‘Data.Vector.Unboxed.Base’
          ‘P.Vector’ is defined in ‘Data.Vector.Primitive’
      The data constructor ‘Data.Vector.Unboxed.Base.V_UnboxViaPrim’
        of newtype ‘U.Vector (U.UnboxViaPrim a)’ is not in scope
    • In the expression:
        ghc-prim-0.9.0:GHC.Prim.coerce
          @(U.Vector (U.UnboxViaPrim Foo) -> U.UnboxViaPrim Foo -> b -> b)
          @(U.Vector Foo -> Foo -> b -> b)
          (G.elemseq @U.Vector @(U.UnboxViaPrim Foo))
      In an equation for ‘G.elemseq’:
          G.elemseq
            = ghc-prim-0.9.0:GHC.Prim.coerce
                @(U.Vector (U.UnboxViaPrim Foo) -> U.UnboxViaPrim Foo -> b -> b)
                @(U.Vector Foo -> Foo -> b -> b)
                (G.elemseq @U.Vector @(U.UnboxViaPrim Foo))
      When typechecking the code for ‘G.elemseq’
        in a derived instance for ‘G.Vector U.Vector Foo’:
        To see the code I am typechecking, use -ddump-deriv
      In the instance declaration for ‘G.Vector U.Vector Foo’
   |
25 | deriving via (U.UnboxViaPrim Foo) instance G.Vector  U.Vector  Foo
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

finally if I fix this too I’ll get output

#!/usr/bin/env cabal
{- cabal:
build-depends:
  , base
  , vector ^>= 0.13
-}
{-# LANGUAGE DerivingVia                #-}
{-# LANGUAGE GeneralisedNewtypeDeriving #-}
{-# LANGUAGE MultiParamTypeClasses      #-}
{-# LANGUAGE StandaloneDeriving         #-}
{-# LANGUAGE TypeFamilies               #-}

module Main where

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

newtype Foo = Foo Int deriving P.Prim

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

main :: IO ()
main = do
  putStrLn "OK"
  pure ()
$ cabal run Test.hs
OK

I propose to amend doctest for UnboxViaPrim to make it working. I have also took liberty to sort imports and qualify imported module’s names in the same way doctest for IsoUnbox does for consistency (in a separate commit for ease of discarding it if it proves too controversial).

@Bodigrim

Copy link
Copy Markdown
Contributor

Thanks for noticing this!

module Data.Vector.Unboxed (
-- * Unboxed vectors
Vector(V_UnboxAs), MVector(..), Unbox,

I don't remember why MVector is exported in full (so MV_UnboxViaPrim is in scope), but Vector isn't (and thus V_UnboxViaPrim isn't in scope). It's really unfortunate to push users to import Data.Vector.Unboxed.Base which does not even provide haddocks.

@lehins
lehins requested a review from Shimuuar October 12, 2022 00:21
@Shimuuar

Copy link
Copy Markdown
Contributor

I don't remember why MVector is exported in full (...), but Vector isn't

It's always been like that 4c7bf23. It's difficult to say what are reasons though.

I think it would be better to add V_UnboxViaPrim to export list as was done for V_UnboxAs it wasn't added because of oversight. This way user won't be forced to import Data.Vector.Unboxed.Base

@Bodigrim

Copy link
Copy Markdown
Contributor

Yes, I agree that exporting V_UnboxViaPrim is a good idea. @sergv would you mind to do this?

@sergv

sergv commented Oct 12, 2022

Copy link
Copy Markdown
Contributor Author

Updated, the only thing being not sure whether to export only V_UnboxViaPrim constructor or all constructors for Vector type family like it's done for MVector type family. I exported only one thing but inconsistency between exports of Vector and MVector bugs me.

@Bodigrim
Bodigrim requested review from Shimuuar and removed request for Shimuuar October 18, 2022 20:38

@Shimuuar Shimuuar left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I forgot about this PR. LGTM. @sergv thank you for your contribution.

@Shimuuar
Shimuuar merged commit 6ec0532 into haskell:master Oct 19, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants