Обобщающая карта AndUnzip

Я ищу простой способ написать функцию

mapAndUnzip :: (Functor f) => (a -> (b,c)) -> f a -> (f b, f c)

Я не совсем уверен, что Functor это достаточно сильное ограничение, но я буду использовать его для конкретности. Я хочу иметь возможность применять эту функцию, когда f имеет тип (чтобы назвать несколько) [], Data.Vector.Unboxed.Vector и мои собственные типы оберток вокруг [a] а также Vector a, (Другие возможные типы включают Array, Репа векторов и т. Д.)

Мое ключевое требование заключается в том, что мне не нужно такое ограничение, как (Unbox (b,c)), только (Unbox b,Unbox c), Subrequirement: вычислить функцию только один раз для каждого элемента ввода.

Я вижу способ сделать это для Vector создавая два изменяемых вектора при отображении входных данных, но я надеюсь, что есть лучший способ, чем создание нового класса и моих собственных экземпляров для разных типов. Специфичный для списка способ, который определяет GHC.Util mapAndUnzip заставляет меня думать, что общее решение может быть невозможным, но я подумал, что получу второе мнение, прежде чем взломать собственное решение.

1 ответ

Functor достаточно, вы можете сделать:

(РЕДАКТИРОВАТЬ: вычислить g только один раз)

mapAndUnzip g fa = (fmap fst fbc, fmap snd fbc)
  where
    fbc = fmap g fa
Другие вопросы по тегам