Using mutable and immutable vectors together is painful
This is actually 2 closely-related issues:
- Importing both
Data.Vector.GenericandData.Vector.Generic.Mutablein the same module means one must qualify all the slice and length ops, for exampletakeanddrop, tho these are effectively the same operations on mutable and immutable vectors. - It is effectively impossible to write one term which works with both mutable and immutable vectors, for examples, all which i needed lately:
tails :: Vector v a => v a -> [v a]tailMay :: Vector v a => v a -> Maybe (v a)wrapSlice :: Vector v a => Int -> Int -> v a -> v a -- slice wrapping back to start if it goes too farwindows :: Vector v a => Int -> v a -> [v a] -- list of all subvectors of given length
It should be possible to use the same function to slice both mutable and immutable vectors. I propose this:
class Slice v where
length :: v a -> Int
unsafeSlice :: Int -> Int -> v a -> v a
and instances for all Vector and MVector types; i believe the other slicing functions can be defined in terms of these.
I can implement this, so let me know whether you approve.
I agree with the goal though not the specific design as specified.
A related but easier to scope out task that would help is improving the mutable vector API
I would suggest also experimenting with a monadic API that picks out via constraint kinds and one of TFs and Fds whether any monad or a primonad is needed. This could be done as a user library on top before going into vector proper. On Sat, Mar 25, 2017 at 5:14 PM M Farkas-Dyck [email protected] wrote:
This is actually 2 closely-related issues:
- Importing both Data.Vector.Generic and Data.Vector.Generic.Mutable in the same module means one must qualify all the slice and length ops, for example take and drop, tho these are effectively the same operations on mutable and immutable vectors.
- It is effectively impossible to write one term which works with both mutable and immutable vectors, for examples, all which i needed lately:
- tails :: Vector v a => v a -> [v a]
- tailMay :: Vector v a => v a -> Maybe (v a)
- wrapSlice :: Vector v a => Int -> Int -> v a -> v a -- slice wrapping back to start if it goes too far
- windows :: Vector v a => Int -> v a -> [v a] -- list of all subvectors of given length
It should be possible to use the same function to slice both mutable and immutable vectors. I propose this:
class Slice v where length :: v a -> Int unsafeSlice :: Int -> Int -> v a -> v a
and instances for all Vector and MVector types; i believe the other slicing functions can be defined in terms of these.
I can implement this, so let me know whether you approve.
— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/haskell/vector/issues/159, or mute the thread https://github.com/notifications/unsubscribe-auth/AAAQwhP78HYa4aabJyEAVcNW0NKjHPWFks5rpYO4gaJpZM4MpN-Q .
A related but easier to scope out task that would help is improving the mutable vector API
What have you in mind?
By the way, what is wrong with the design as proposed? (Not being defensive, merely wanting to filter out any future ideas with the same deficiencies.)
For code to run in both pure and mutable contexts it needs to be in some monad. On Sun, Mar 26, 2017 at 1:26 AM M Farkas-Dyck [email protected] wrote:
By the way, what is wrong with the design as proposed? (Not being defensive, merely wanting to filter out any future ideas with the same deficiencies.)
— You are receiving this because you commented.
Reply to this email directly, view it on GitHub https://github.com/haskell/vector/issues/159#issuecomment-289259553, or mute the thread https://github.com/notifications/unsubscribe-auth/AAAQwsfD_mEIzo3EqNUNs51XdfmSC_Z-ks5rpfcTgaJpZM4MpN-Q .
I'm not sure unifying the entire API is an ideal solution, or even related to this request.
For one, the API is already the same for these functions. Slicing is not effectful for either type of vector.
For two, it makes the immutable API more annoying to use.
For three, I have no idea if it would be possible to do fusion if the entire immutable API were changed to be monadic, because people would need to write binds to piece together operations, instead of just composing functions. If the immutable API has functions ending in any Monad, any failure to specialize that to Identity would almost certainly kill fusion.
So, if that's the objection, I'm more favorable toward factoring out the existing slicing into a common API. I don't know if I like the class name Slice, but I don't have a better suggestion at the moment.
I'm not suggesting dropping the current API. Merely suggesting an approach to provide a shared API. Especially since internally a lot of the pure stuff is merely running monadic pure code in the identity monad.
But I do agree that mutable and pure metadata about slicing and length could be in a shared API. On Sat, Apr 1, 2017 at 12:07 AM dolio [email protected] wrote:
I'm not sure unifying the entire API is an ideal solution, or even related to this request.
For one, the API is already the same for these functions. Slicing is not effectful for either type of vector.
For two, it makes the immutable API more annoying to use.
For three, I have no idea if it would be possible to do fusion if the entire immutable API were changed to be monadic, because people would need to write binds to piece together operations, instead of just composing functions. If the immutable API has functions ending in any Monad, any failure to specialize that to Identity would almost certainly kill fusion.
So, if that's the objection, I'm more favorable toward factoring out the existing slicing into a common API. I don't know if I like the class name Slice, but I don't have a better suggestion at the moment.
— You are receiving this because you commented.
Reply to this email directly, view it on GitHub https://github.com/haskell/vector/issues/159#issuecomment-290893154, or mute the thread https://github.com/notifications/unsubscribe-auth/AAAQwjYGMWjVzPIT_ufwZ6X58xfJoGprks5rrc1-gaJpZM4MpN-Q .