2017-01-19 6 views
10

Рассматривая, как наилучшим образом отобразить карту, то есть 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-traversabledoes the same thing also for unboxed vectors; здесь это кажется еще более ужасным по производительности.

Теперь я не удивлюсь, если бы vector действительно мог сплавить многие из этих взломанных обходов в гораздо более эффективную форму, но все же - кажется, есть фундаментальная проблема, мешающая нам осуществить обход на массив сразу. Есть ли «глубокая причина» для этой неспособности?

+1

Отсутствие экземпляра для 'U.Vector' связано с ограничением' Unbox' для элементов. См. [* Почему массивы unboxed не являются экземплярами складных? *) (Http://stackoverflow.com/q/36322904/2751851) (ответ Соняна также содержит некоторые важные комментарии о * mono-traversable *). – duplode

+3

Конечно, но это не то, о чем я прошу. Мне не нужен фактический экземпляр «Traversable», мне просто нужен эффективный обход! И «mono-traversable» не предлагает этого. – leftaroundabout

+0

К сожалению, я не заметил «очевидно» в вашем первом абзаце :) – duplode

ответ

2

После прочтения соответствующего источника vector и пытаемся сделать mapM работы с Applicative Я думаю, что причина, почему Data.Vector.Unboxed.Vector не имеет traverse :: (Applicative f, Unbox a, Unbox b) -> (a -> f b) -> Vector a -> f (Vector b) функций и 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 repo: Weaken constraint on mapM.

Отказ от ответственности: Я действительно не знаю, как работает слияние. Я не знаю, как работает vector.

Смежные вопросы