Обобщающая карта 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