在考虑如何最好地映射(traverse
,a -> Maybe a
- Kleisli而不是unboxed vector时,我寻找了一个现有的实现。显然U.Vector
不是Traversable
,而是it does supply a mapM
,Maybe
当然可以正常工作。
但问题是:真的需要Monad
约束吗?好吧,事实证明,即使是boxed vectors cheat for the Traversable
instance:它们实际上只是遍历一个列表,它们从/转换为:
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;在这里,这似乎更加令人毛骨悚然。
现在,如果vector
实际上能够将这些被攻击的遍历融合成更有效的形式,我不会感到惊讶,但仍然 - 似乎存在根本问题,阻止我们立即在阵列上实现遍历。这种无能是否存在“深层原因”?
答案 0 :(得分:2)
在阅读vector
的相关来源并尝试mapM
与Applicative
合作后,我认为Data.Vector.Unboxed.Vector
没有traverse :: (Applicative f, Unbox a, Unbox b) -> (a -> f b) -> Vector a -> f (Vector b)
的原因} function和Data.Vector.Vector
没有原生traverse
是融合代码。罪犯是以下Stream
类型:
-- Data/Vector/Fusion/Stream/Monadic.hs Line: 137
-- | Result of taking a single step in a stream
data Step s a where
Yield :: a -> s -> Step s a
Skip :: s -> Step s a
Done :: Step s a
-- | Monadic streams
data Stream m a = forall s. Stream (s -> m (Step s a)) s
这在内部用于实现mapM
。 m
与您对Data.Vector.Unboxed.mapM
的初次调用相同。但是因为此流的主干位于m
仿函数内部,所以如果您只有m
的应用,则无法使用它。
请参阅vector
GitHub回购中的此问题:Weaken constraint on mapM。
免责声明:我真的不知道融合是如何运作的。我不知道vector
是如何运作的。