Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve UnboxViaPrim docs #450

Merged
merged 3 commits into from
Oct 19, 2022
Merged

Improve UnboxViaPrim docs #450

merged 3 commits into from
Oct 19, 2022

Conversation

sergv
Copy link
Contributor

@sergv sergv commented Oct 11, 2022

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
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
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
Contributor

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

@sergv
Copy link
Contributor Author

sergv commented Oct 12, 2022

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
Copy link
Contributor

@Shimuuar Shimuuar left a comment

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.

None yet

3 participants