1

Is there a nicer way to write the following function fs' with functors or applicatives?

fncnB = (* 2)
fncnA = (* 3)
fs' fs = zip (map (fncnA . fst) fs) $ map (fncnB . snd) fs

I see from this question that I could rely on the functor instance of lists to map a single function acting over both elements of each tuple, or e.g. on the applicative instance of tuples to apply functions to just the second-half of a two-tuple, but I'm curious how functors and applicatives fit into the picture of operating over lists of multi-component data types.

cronburg
  • 892
  • 1
  • 8
  • 24
  • Not related to Functor or Applicative, but you could rewrite this nicely with a list comprehension: `fs' fs = [(fncnA x, fncnB y) | (x, y) <- fs]` – Robin Zigmond Mar 22 '19 at 19:43
  • 3
    Or, using `Arrow` methods, simply `fs' = map (fncnA &&& fncnB)`. (I think. I'm not really experienced with Arrows.) – Robin Zigmond Mar 22 '19 at 19:46
  • 3
    @RobinZigmond: Right idea, wrong function – you want [`(***)`](https://hackage.haskell.org/package/base-4.12.0.0/docs/Control-Arrow.html#v:-42--42--42-). [`(&&&)`](https://hackage.haskell.org/package/base-4.12.0.0/docs/Control-Arrow.html#v:-38--38--38-) would be for `((* 2) &&& (* 3)) 5 == (10,15)`. – Antal Spector-Zabusky Mar 22 '19 at 20:19
  • Thanks @AntalSpector-Zabusky, I knew I'd get mixed up somewhere :) – Robin Zigmond Mar 22 '19 at 20:22

2 Answers2

11

A tuple is a bifunctor, so bimap is available.

import Data.Bifunctor

fncnB = (* 2)
fncnA = (* 3)
fs' = map (bimap fncnA fncnB)

No third-party libraries required.

0

what you need is the mapPair function, it's defined in the utility-ht package but it's just

mapPair :: (a -> c, b -> d) -> (a,b) -> (c,d)
mapPair (f,g) (a,b) = (f a, g b) 

use

Prelude> mapPair ((* 2), (* 3)) (2,3)
(4,9)

or

Prelude> map (mapPair ((* 2), (* 3))) [(1,2),(2,3)]
[(2,6),(4,9)]
karakfa
  • 66,216
  • 7
  • 41
  • 56