-
Notifications
You must be signed in to change notification settings - Fork 143
Export constructors for vectors from unsafe module #540
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
base: master
Are you sure you want to change the base?
Conversation
f41d88a to
702c7b0
Compare
I think it would make sense to add an |
|
Yes it seems in the end library authors need to provide access to internals and it's better to do it systematic way. I hoped to get away with single |
e7237e3 to
32c7585
Compare
|
I implemented unsafe modules for everything except General idea is to move definition of data type and all function that work directly on vector representation into Unsafe module. It has nice side effect of separating code specific to vector type from endless specializations. At the moment all function safe and unsafe are simply reexported from safe modules. Deprecation warning is only applied to pattern synonym. |
32c7585 to
5125015
Compare
|
Now PR is mostly done. Implementation follows rules below:
Remaining questions
|
6e2ceb8 to
a44dfb1
Compare
They contain publicly accessible definitions of vector data types and unsafe operations on structure.
for unsafe unboxed vectors
We have 3 sorts of data instances:
1. Constructors that we must exports. Data instances which are used in deriving
via (UnboxViaPrim etc.). When constructors aren't visible deriving won't
work. They were exported before.
2. Constructors which are safe to use. Newtype vectors over underlying
representation. Now they're exported from both immutable and mutable
3. Dangerous and unsafe ones: tuple and unit instances. They're exported from
Unsafe module. Mutable module reexports deprecated pattern synonym.
a44dfb1 to
67c9fcd
Compare
|
I think PR is ready. |
|
@lehins Do you have any comments? If no I'm going to merge this PR next weekend |
|
Sorry, I did want to review this PR. |
|
No problem. I worked on PR for 4 month on and off. It can wait. On second thought dropping D.V.Unboxed.Base was too risque. It's better to deprecate that module and reexport content of new D.V.Unboxed.Unsafe |
lehins
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Aside from some functions unfairly being tainted as unsafe, I believe this is a very nice start for separating safe vs unsafe interface
| -- Conversions - Arrays | ||
| -- ----------------------------- | ||
|
|
||
| -- | /O(n)/ Make a copy of a mutable array to a new mutable vector. | ||
| -- | ||
| -- @since 0.12.2.0 | ||
| fromMutableArray :: PrimMonad m => MutableArray (PrimState m) a -> m (MVector (PrimState m) a) | ||
| {-# INLINE fromMutableArray #-} | ||
| fromMutableArray marr = | ||
| let size = sizeofMutableArray marr | ||
| in MVector 0 size `liftM` cloneMutableArray marr 0 size | ||
|
|
||
| -- | /O(n)/ Make a copy of a mutable vector into a new mutable array. | ||
| -- | ||
| -- @since 0.12.2.0 | ||
| toMutableArray :: PrimMonad m => MVector (PrimState m) a -> m (MutableArray (PrimState m) a) | ||
| {-# INLINE toMutableArray #-} | ||
| toMutableArray (MVector offset size marr) = cloneMutableArray marr offset size |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not sure I understand why these two functions are moved to the unsafe module?
They both allocate a new array and make a full copy using safe bounds. I can't see anything unsafe about them.
| type IOVector = MVector RealWorld | ||
| type STVector s = MVector s |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think these two synonyms can go back into the safe module. They are totally safe and aren't needed in this module
| -- Conversions - Lazy vectors | ||
| -- ----------------------------- | ||
|
|
||
| -- | /O(1)/ Convert strict array to lazy array | ||
| toLazy :: Vector a -> V.Vector a | ||
| toLazy (Vector v) = v | ||
|
|
||
| -- | /O(n)/ Convert lazy array to strict array. This function reduces | ||
| -- each element of vector to WHNF. | ||
| fromLazy :: V.Vector a -> Vector a | ||
| fromLazy vec = liftRnf (`seq` ()) v `seq` v where v = Vector vec | ||
|
|
||
|
|
||
| -- Conversions - Arrays | ||
| -- ----------------------------- | ||
|
|
||
| -- | /O(n)/ Convert an array to a vector and reduce each element to WHNF. | ||
| -- | ||
| -- @since 0.13.2.0 | ||
| fromArray :: Array a -> Vector a | ||
| {-# INLINE fromArray #-} | ||
| fromArray arr = liftRnf (`seq` ()) vec `seq` vec | ||
| where | ||
| vec = Vector $ V.fromArray arr | ||
|
|
||
| -- | /O(n)/ Convert a vector to an array. | ||
| -- | ||
| -- @since 0.13.2.0 | ||
| toArray :: Vector a -> Array a | ||
| {-# INLINE toArray #-} | ||
| toArray (Vector v) = V.toArray v |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same with these guys. I don't think there is anything unsafe about them at all. They all preserve the necessary invariants. They force the elements when needed and make copies when slicing cannot be preserved.
| -- @since 0.13.2.0 | ||
| toArraySlice :: Vector a -> (Array a, Int, Int) | ||
| {-# INLINE toArraySlice #-} | ||
| toArraySlice (Vector v) = V.toArraySlice v |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This one I can believe, for example, that it can be unsafe, since it is possible that some part of the result array will be uninitialized
| -- Conversions - Arrays | ||
| -- ----------------------------- | ||
|
|
||
| -- | /O(1)/ Convert an array to a vector. | ||
| -- | ||
| -- @since 0.12.2.0 | ||
| fromArray :: Array a -> Vector a | ||
| {-# INLINE fromArray #-} | ||
| fromArray arr = Vector 0 (sizeofArray arr) arr | ||
|
|
||
| -- | /O(n)/ Convert a vector to an array. | ||
| -- | ||
| -- @since 0.12.2.0 | ||
| toArray :: Vector a -> Array a | ||
| {-# INLINE toArray #-} | ||
| toArray (Vector offset len arr) | ||
| | offset == 0 && len == sizeofArray arr = arr | ||
| | otherwise = cloneArray arr offset len |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here. These conversions are totally safe
|
@lehins Yes I moved some safe functions to Real question is what should go into
What about |
I do not agree with this at all. This will make people wrongfully believe that those functions are unsafe. And I can certainly see harm in it!
Anything that is unsafe should IMHO be eventually moved:
Totally disagree. There is nothing wrong in providing a safe function that itself uses unsafe constructor.
Yes, I believe so.
Yes, I believe so as well
I do believe that would be a good idea for consistency and safety sake
Doesn't sound too bad. Something like this?
If these seem too long maybe we could shorten them:
We could also provide matching type synonyms, so users could just import the type synonyms and use Generic interface if they so choose. |
Put module name in DEPRECATE pragma in quotes. This way haddock is able to link to module. Use MVector(MVector) in export list when importing from module which exports pattern instead of constructor. This approach doesn't work when pattern is defined in module. Co-authored-by: Alexey Kuleshevich <alexey@kuleshevi.ch>
43bbd9e to
8cbf15a
Compare
|
It turns that export of Also haddock doesn't link properly |
So we disagree on this but your approach is valid as well and I don't feel to strong about his. Let do it your way. This PR is uncomfortably big already so I propose following plan:
BTW exactly this was requested in #240 but I think it's better to do this separately |
|
I 100% agree with this plan: #540 (comment) |
This is proof of concept implementation of #535 for primitive vectors.
Idea work out nicely. There's one small complication. It makes sense to define unsafe function working on representation of a vector but we get name clashes: both mutable and pure primitive vectors defined
unsafeCastso it pprobab;y makes sense to keep such function where they're currently definedReviews are very welcome.
Fixes #535, Fixes #524, Fixes #517, Fixes #506, Fixes #492, Fixes #171