mapFst and mapSnd

Hi all, I often find myself needing the following definitions: mapPair :: (a -> b) -> (c -> d) -> (a,c) -> (b,d) mapPair f g (x,y) = (f x, g y) mapFst :: (a -> b) -> (a,c) -> (b,c) mapFst f = mapPair f id mapSnd :: (b -> c) -> (a,b) -> (a,c) mapSnd = mapPair id But they seem missing from the prelude and Hoogle or Hayoo only turn up versions of them in packages like scion or fgl. Has anyone else felt the need for these functions? Am I missing some generalisation of them perhaps? Regards, Dominique

You might want to look at the arrow type class and the instance for (->). Ben On 28 May 2013 09:56, "Dominique Devriese" < dominique.devriese@cs.kuleuven.be> wrote:
Hi all,
I often find myself needing the following definitions:
mapPair :: (a -> b) -> (c -> d) -> (a,c) -> (b,d) mapPair f g (x,y) = (f x, g y)
mapFst :: (a -> b) -> (a,c) -> (b,c) mapFst f = mapPair f id
mapSnd :: (b -> c) -> (a,b) -> (a,c) mapSnd = mapPair id
But they seem missing from the prelude and Hoogle or Hayoo only turn up versions of them in packages like scion or fgl. Has anyone else felt the need for these functions? Am I missing some generalisation of them perhaps?
Regards, Dominique
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

These are present in Control.Arrow as (***), first and second respectively. They are easy to overlook because they work for *all* arrows, not just functions. So the type signatures look like: first :: Arrow a => a b c -> a (b, d) (c, d) If you replace a with (->), you'll see that this is exactly like your mapFst. On Tue, May 28, 2013 at 1:54 AM, Dominique Devriese < dominique.devriese@cs.kuleuven.be> wrote:
Hi all,
I often find myself needing the following definitions:
mapPair :: (a -> b) -> (c -> d) -> (a,c) -> (b,d) mapPair f g (x,y) = (f x, g y)
mapFst :: (a -> b) -> (a,c) -> (b,c) mapFst f = mapPair f id
mapSnd :: (b -> c) -> (a,b) -> (a,c) mapSnd = mapPair id
But they seem missing from the prelude and Hoogle or Hayoo only turn up versions of them in packages like scion or fgl. Has anyone else felt the need for these functions? Am I missing some generalisation of them perhaps?
Regards, Dominique
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

On Tue, May 28, 2013 at 7:46 PM, Dominique Devriese < dominique.devriese@cs.kuleuven.be> wrote:
2013/5/28 Tikhon Jelvis
: These are present in Control.Arrow as (***), first and second respectively.
Right, thanks. Strange that neither Hayoo nor Hoogle turned these up..
HLint suggested Control.Arrow.&&& and Control.Arrow.first to me the other day: $ hlint Checker.hs Checker.hs:65:5: Warning: Reduce duplication Found: topdir <- ask md5file <- computeChecksumFilename f hasChecksum <- liftM not $ isChecksumMissing f Why not: Combine with Checker.hs:81:5 Checker.hs:127:96: Warning: Use &&& Found: \ x -> (s3Path x, s3Md5sum x) Why not: s3Path Control.Arrow.&&& s3Md5sum Checker.hs:153:42: Warning: Use first Found: \ (x, y) -> (trimPathPrefix path x, y) Why not: Control.Arrow.first (trimPathPrefix path) 3 suggestions Some people that I know have HLint incorporated into their vim sessions, I think using Syntastic. Cheers, -- Carlo Hamalainen http://carlo-hamalainen.net

On Tue, May 28, 2013 at 10:54 AM, Dominique Devriese < dominique.devriese@cs.kuleuven.be> wrote:
Hi all,
I often find myself needing the following definitions:
mapPair :: (a -> b) -> (c -> d) -> (a,c) -> (b,d) mapPair f g (x,y) = (f x, g y)
That's Control.Arrow.(***), e.g.: ghci> (+3) *** (*5) $ (20,30) (23,150)
mapFst :: (a -> b) -> (a,c) -> (b,c) mapFst f = mapPair f id
mapSnd :: (b -> c) -> (a,b) -> (a,c) mapSnd = mapPair id
That's Control.Arrow.{first, second}:
ghci> first (+10) (1,1)
(11,1)
ghci> second (+10) (1,1)
(1,11)
G
--
Gregory Collins

I have them defined for my stuff. Generally I find it much quicker to "roll my own" than to (1) ask on this list if someone else has done it... (2) look at arrows or MyFavouriteCategoryTheoryBitOfFPBecauseICantGetAbstractEnough and the try to figure out what is going on. The joy of Haskell is both that rolling your own is often so easy, and that there are lots of approaches out there that allow you to get abstract as well... Regards, Andrew (Engineering graduate, feet still firmly embedded in concrete :-) On 28 May 2013, at 09:54, Dominique Devriese wrote:
Hi all,
I often find myself needing the following definitions:
mapPair :: (a -> b) -> (c -> d) -> (a,c) -> (b,d) mapPair f g (x,y) = (f x, g y)
mapFst :: (a -> b) -> (a,c) -> (b,c) mapFst f = mapPair f id
mapSnd :: (b -> c) -> (a,b) -> (a,c) mapSnd = mapPair id
But they seem missing from the prelude and Hoogle or Hayoo only turn up versions of them in packages like scion or fgl. Has anyone else felt the need for these functions? Am I missing some generalisation of them perhaps?
Regards, Dominique
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
-------------------------------------------------------------------- Andrew Butterfield Tel: +353-1-896-2517 Fax: +353-1-677-2204 Lero@TCD, Head of Foundations & Methods Research Group Director of Teaching and Learning - Undergraduate, School of Computer Science and Statistics, Room G.39, O'Reilly Institute, Trinity College, University of Dublin http://www.scss.tcd.ie/Andrew.Butterfield/ --------------------------------------------------------------------

Dne 28.5.2013 10:54, Dominique Devriese napsal(a):
Hi all,
I often find myself needing the following definitions:
mapPair :: (a -> b) -> (c -> d) -> (a,c) -> (b,d) mapPair f g (x,y) = (f x, g y)
mapFst :: (a -> b) -> (a,c) -> (b,c) mapFst f = mapPair f id
mapSnd :: (b -> c) -> (a,b) -> (a,c) mapSnd = mapPair id
But they seem missing from the prelude and Hoogle or Hayoo only turn up versions of them in packages like scion or fgl. Has anyone else felt the need for these functions? Am I missing some generalisation of them perhaps? Apart from Arrows, there is also package "bifunctors" that defines this functionality for (,), Either and a few others: http://hackage.haskell.org/packages/archive/bifunctors/3.2.0.1/doc/html/Data...
Petr Pudlak

See Agda.Utils.Tuple :-) -- | Bifunctoriality for pairs. (-*-) :: (a -> c) -> (b -> d) -> (a,b) -> (c,d) (f -*- g) ~(x,y) = (f x, g y) -- | @mapFst f = f -*- id@ mapFst :: (a -> c) -> (a,b) -> (c,b) mapFst f ~(x,y) = (f x, y) -- | @mapSnd g = id -*- g@ mapSnd :: (b -> d) -> (a,b) -> (a,d) mapSnd g ~(x,y) = (x, g y) I think mapPair, mapFst, and mapSnd are canonical names that could be added to Data.Tuple. But if you suggest this on libraries@haskell.org, you get probably turned down, see e.g. http://comments.gmane.org/gmane.comp.lang.haskell.libraries/17411 Cheers, Andreas On 28.05.2013 15:34, Petr Pudlák wrote:
Dne 28.5.2013 10:54, Dominique Devriese napsal(a):
Hi all,
I often find myself needing the following definitions:
mapPair :: (a -> b) -> (c -> d) -> (a,c) -> (b,d) mapPair f g (x,y) = (f x, g y)
mapFst :: (a -> b) -> (a,c) -> (b,c) mapFst f = mapPair f id
mapSnd :: (b -> c) -> (a,b) -> (a,c) mapSnd = mapPair id
But they seem missing from the prelude and Hoogle or Hayoo only turn up versions of them in packages like scion or fgl. Has anyone else felt the need for these functions? Am I missing some generalisation of them perhaps? Apart from Arrows, there is also package "bifunctors" that defines this functionality for (,), Either and a few others: http://hackage.haskell.org/packages/archive/bifunctors/3.2.0.1/doc/html/Data...
Petr Pudlak
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
-- Andreas Abel <>< Du bist der geliebte Mensch. Theoretical Computer Science, University of Munich Oettingenstr. 67, D-80538 Munich, GERMANY andreas.abel@ifi.lmu.de http://www2.tcs.ifi.lmu.de/~abel/

`mapPair` also exists as `tup2` in patch-combinators: http://hackage.haskell.org/package/patch-combinators / Emil 2013-05-28 16:01, Andreas Abel skrev:
See Agda.Utils.Tuple :-)
-- | Bifunctoriality for pairs. (-*-) :: (a -> c) -> (b -> d) -> (a,b) -> (c,d) (f -*- g) ~(x,y) = (f x, g y)
-- | @mapFst f = f -*- id@ mapFst :: (a -> c) -> (a,b) -> (c,b) mapFst f ~(x,y) = (f x, y)
-- | @mapSnd g = id -*- g@ mapSnd :: (b -> d) -> (a,b) -> (a,d) mapSnd g ~(x,y) = (x, g y)
I think mapPair, mapFst, and mapSnd are canonical names that could be added to Data.Tuple. But if you suggest this on libraries@haskell.org, you get probably turned down, see e.g.
http://comments.gmane.org/gmane.comp.lang.haskell.libraries/17411
Cheers, Andreas
On 28.05.2013 15:34, Petr Pudlák wrote:
Dne 28.5.2013 10:54, Dominique Devriese napsal(a):
Hi all,
I often find myself needing the following definitions:
mapPair :: (a -> b) -> (c -> d) -> (a,c) -> (b,d) mapPair f g (x,y) = (f x, g y)
mapFst :: (a -> b) -> (a,c) -> (b,c) mapFst f = mapPair f id
mapSnd :: (b -> c) -> (a,b) -> (a,c) mapSnd = mapPair id
But they seem missing from the prelude and Hoogle or Hayoo only turn up versions of them in packages like scion or fgl. Has anyone else felt the need for these functions? Am I missing some generalisation of them perhaps? Apart from Arrows, there is also package "bifunctors" that defines this functionality for (,), Either and a few others: http://hackage.haskell.org/packages/archive/bifunctors/3.2.0.1/doc/html/Data...
Petr Pudlak
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

On Tue, May 28, 2013 at 1:54 AM, Dominique Devriese
Hi all,
I often find myself needing the following definitions:
mapPair :: (a -> b) -> (c -> d) -> (a,c) -> (b,d) mapPair f g (x,y) = (f x, g y)
mapFst :: (a -> b) -> (a,c) -> (b,c) mapFst f = mapPair f id
mapSnd :: (b -> c) -> (a,b) -> (a,c) mapSnd = mapPair id
But they seem missing from the prelude and Hoogle or Hayoo only turn up versions of them in packages like scion or fgl. Has anyone else felt the need for these functions? Am I missing some generalisation of them perhaps?
One generalization of them is to lenses. For example `lens` has "both", "_1", "_2", such that "mapPair = over both", "mapFst = over _1", etc., but you can also get "fst = view _1", "set _2 = \y' (x,_) -> (x,y')", and so on. (Since "both" refers to two elements, you end up with "view both = \(x,y) -> mappend x y".) The types you end up with are simple generalizations of mapFoo, with just an extra Functor or Applicative (think mapMFoo): both :: Applicative f => (a -> f b) -> (a,a) -> f (b,b) both f (x,y) = (,) <$> f x <*> g y _2 :: Functor f => (a -> f b) -> (e,a) -> f (e,b) _2 f (x,y) = (,) x <$> f y With an appropriate choice of f you can get many useful functions. Shachaf

On Thu, May 30, 2013 at 7:12 PM, Shachaf Ben-Kiki
One generalization of them is to lenses. For example `lens` has "both", "_1", "_2", such that "mapPair = over both", "mapFst = over _1", etc., but you can also get "fst = view _1", "set _2 = \y' (x,_) -> (x,y')", and so on. (Since "both" refers to two elements, you end up with "view both = \(x,y) -> mappend x y".) The types you end up with are simple generalizations of mapFoo, with just an extra Functor or Applicative (think mapMFoo):
both :: Applicative f => (a -> f b) -> (a,a) -> f (b,b) both f (x,y) = (,) <$> f x <*> g y
_2 :: Functor f => (a -> f b) -> (e,a) -> f (e,b) _2 f (x,y) = (,) x <$> f y
With an appropriate choice of f you can get many useful functions.
I spoke too quickly -- your mapPair is something different. Indeed bimap (or (***), if you prefer base) is the place to find it -- lenses don't really fit here. My "both" is for mapping one function over both elements. Shachaf

class BinaryFunctor f where
bimap :: (a -> c) -> (b -> d) -> f a b -> f c d
mapFst = (`bimap id`)
mapSnd = bimap id
On 31/05/2013 12:16 PM, "Shachaf Ben-Kiki"
On Thu, May 30, 2013 at 7:12 PM, Shachaf Ben-Kiki
wrote: One generalization of them is to lenses. For example `lens` has "both", "_1", "_2", such that "mapPair = over both", "mapFst = over _1", etc., but you can also get "fst = view _1", "set _2 = \y' (x,_) -> (x,y')", and so on. (Since "both" refers to two elements, you end up with "view both = \(x,y) -> mappend x y".) The types you end up with are simple generalizations of mapFoo, with just an extra Functor or Applicative (think mapMFoo):
both :: Applicative f => (a -> f b) -> (a,a) -> f (b,b) both f (x,y) = (,) <$> f x <*> g y
_2 :: Functor f => (a -> f b) -> (e,a) -> f (e,b) _2 f (x,y) = (,) x <$> f y
With an appropriate choice of f you can get many useful functions.
I spoke too quickly -- your mapPair is something different. Indeed bimap (or (***), if you prefer base) is the place to find it -- lenses don't really fit here. My "both" is for mapping one function over both elements.
Shachaf
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

On Thu, May 30, 2013 at 10:56 PM, Tony Morris
class BinaryFunctor f where bimap :: (a -> c) -> (b -> d) -> f a b -> f c d
mapFst = (`bimap id`) mapSnd = bimap id
There's a bifunctors package with: class Bifunctor f where bimap :: ... first :: a -> b -> f a c -> f b c second :: b -> c -> f a b -> f a c
participants (12)
-
Alexander Solla
-
Andreas Abel
-
Andrew Butterfield
-
Benjamin Edwards
-
Carlo Hamalainen
-
Dominique Devriese
-
Emil Axelsson
-
Gregory Collins
-
Petr Pudlák
-
Shachaf Ben-Kiki
-
Tikhon Jelvis
-
Tony Morris