While pondering how to best map, i.e. traverse
, an a -> Maybe a
-Kleisli over an unboxed vector, I looked for an existing implementation. Obviously U.Vector
is not Traversable
, but it does supply a mapM
, which for Maybe
of course works just fine.
But the question is: is the Monad
constraint really needed? Well, it turns out that even boxed vectors cheat for the Traversable
instance: they really just traverse a list, which they convert from/to:
instance Traversable.Traversable Vector where
{-# INLINE traverse #-}
traverse f xs = Data.Vector.fromList Applicative.<$> Traversable.traverse f (toList xs)
mono-traversable
does the same thing also for unboxed vectors; here this seems even more gruesome performance-wise.
Now, I wouldn't be surprised if vector
was actually able to fuse many of these hacked traversals into a far more efficient form, but still – there seems to be a fundamental problem, preventing us from implementing a traversal on an array right away. Is there any “deep reason” for this inability?
U.Vector
has to do with theUnbox
constraint on the elements. See Why are unboxed arrays not an instance of foldable? (the answer, by Snoyman, also includes some relevant comments about mono-traversable). – RafaelrafaelaTraversable
instance, I just need an efficient traversal! Andmono-traversable
doesn't offer this. – HelminthicTraversable
instances for records with many fields are "efficient" in some sense. In fact I wouldn't be surprised if traversing a 100-element vector (with the above implementation that converts to and from lists) was cheaper than the derived instance for a record with 100 fields, at least for certain monads. – BristolunsafeDupablePerformIO
+unsafeFreeze
could do it, I think. – Cupule