-
Notifications
You must be signed in to change notification settings - Fork 139
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
Discussion: High-level functions that can convert between vector types #373
Comments
The whole point of convert is that it should work well with fusion, so I think this is the proper way to approach this: atIndices :: (VG.Vector vector a) => vector a -> VU.Vector Int -> vector a
atIndices xs = VG.map (xs VG.!) . convert I am pretty sure PS. I wasn't 100% sure because the question has |
Oops right, it was a paste error, I've fixed it now.
When specialising to
still exists. In my code base this happens quite a bit, because for some types For example, I cannot use the convertingVectorMap :: (VG.Vector vectorA a, VG.Vector vectorB b) => (a -> b) -> vectorA a -> vectorB b
convertingVectorMap f va =
VG.map f (VG.convert va) This does not typecheck as expected:
because |
Just to provide a more concrete example, I may need to convert between e.g. a |
I see what you mean and what the actual problem is. Definition of map :: (Vector v a, Vector v' b) => (a -> b) -> v a -> v' b
{-# INLINE map #-}
map f = unstream . inplace (S.map f) id . Bundle.reVector . stream Issue is that the We could potentially allow all function in Generic vector to change the type of vector from input to output by using One way or another we aren't adding a whole bunch of new functions like FYI, the suggested solution |
That looks great, thanks! Easy full copy-paste for myself and others: import qualified Data.Vector.Generic as VG
import qualified Data.Vector.Fusion.Bundle as Bundle
import qualified Data.Vector.Fusion.Stream.Monadic as Stream
-- | Like `VG.map`, but can convert to another vector type.
convertingVectorMap :: (VG.Vector vectorA a, VG.Vector vectorB b) => (a -> b) -> vectorA a -> vectorB b
convertingVectorMap f =
-- Implemetation from https://github.com/haskell/vector/issues/373#issuecomment-808819064
VG.unstream . Bundle.inplace (Stream.map f) id . Bundle.reVector . VG.stream
{-# INLINE convertingVectorMap #-}
Thanks, that's what I feared!
It would also be backwards-incompatible because while the current functions are certainly correctly expressed by the vector-type-changing ones, the more general type signatures make for looser type inference, creating free type variables that the user now has to pin down. I wonder if it would make sense to make an experimental I'll rename the issue to turn it from a feature request for that specific function, into a general discussion of the vector-converting-functions idea. |
Cool, I was about to open a new issue for this. Here is my summary: All functions in map :: (Vector v a, Vector v b) => (a -> b) -> v a -> v b Note that the One would think that It would be useful to provide this ability of changing the type of a vector from input to output, i.e.: map :: (Vector v1 a, Vector v2 b) => (a -> b) -> v1 a -> v2 b But it seems like that requires removal of So, this question is for @Bodigrim, @Shimuuar and anyone else that might have an opinion on this topic. Is this a worthwhile goal to pursue and are the benefits worth it? Thus far I see pros:
Cons:
Alternative solution would be to mirror Generic API in a separate module that implements this idea without dropping
|
I think that making functions in Generic type-changing is very-very breaking change. It makes it impossible to write functions that are polymorphic in vector type. Since type inference is of no help you'll have to annotate everything. On related note. Currently we can leak implementation details in API. For example: foo :: (Vector v A, Vector v B, Vector v C) ⇒ v A → v C
foo = VG.map (h :: B → C) . VG.filter p . VG.map (f :: A → B) vector of B should fuse away though it may not so we do need dictionary for |
Edit: Issue description of the underlying problem #373 (comment)
Below is the original question that led to it:
I often work with indices that I'd like to store in
Unboxed.Vector Int
vectors, andGeneric.Vector vector a
vectors into which those indices point.At some point I have to resolve the indices back into the original generic vector type. I would like to do:
(This is basically the same as
myVector[indicesVector]
does in Python'snumpy
.)However in the above,
VG.map (xs VG.!) indices
does not typecheck, beausemap
requires that the input vector type be the same as the output vector type.Thus it would be awesome to have a
convertingMap
function that combinesmap
withconvert
, of type:Edit: Solution for this specific function due to @lehins in #373 (comment).
Alternatives considered:
convertingMap vals f = VG.map f (VG.convert vals)
orVG.convert (VG.map f vals)
isn't great, because it requires thatv
andw
can store the same elements, which sometimes isn't the case, e.g. I can have a dataD1
that only works withUnboxed
and dataD2
that only works withStorable
.The text was updated successfully, but these errors were encountered: