6

I am searching for a function which looks something similar to this:

withSelf :: (a -> b) -> a -> (a, b) withSelf f x = (x, f x)

I have searched with Hoogle for such a function; I searched for (a -> b) -> a -> (a, b) and a -> (a -> b) -> (a, b), neither of which were conclusive. The Hackage page on Data.Tuple doesn't have what I'm looking for either.

I'm aware that it's trivial to write, but I want to write idiomatic Haskell where possible, and avoid re-inventing the wheel.

Cœur
  • 37,241
  • 25
  • 195
  • 267
Tom Galvin
  • 861
  • 7
  • 12
  • Hayoo will find some: http://hayoo.fh-wedel.de/?query=%28a+-%3E+b%29+-%3E+a+-%3E+%28a%2Cb%29 but I doubt that those are more idiomatic (if you have to fetch those libs just for this) than redefining it quick and easy – Random Dev Mar 29 '15 at 17:20
  • 1
    One of the nice things about very polymorphic functions like this in a language like Haskell is that there's basically only one way to define a function with type `(a -> b) -> a -> (a, b)`. So in a sense you don't have to worry about reinventing wheels like this; the type system *forces* your wheel to be just as good as anyone else's! ;) – Ben Mar 29 '15 at 20:53

2 Answers2

7

The section (id &&&) does what you want:

> import Control.Arrow
> :t (id &&&)
(id &&&) :: (a -> c') -> a -> (a, c')
> (id &&&) succ 4
(4,5)
chi
  • 111,837
  • 3
  • 133
  • 218
  • 2
    I knew when I read the question that the answer would be in `Control.Arrow`, but I can never, ever remember what the different functions in there do. – dfeuer Mar 29 '15 at 17:39
  • 4
    I like this answer - although I hope I will never see something like this in *real* code ;) (to the uninitiated (noob) *eye* (like mine) `\f a -> (a, f a)` is just easier to read) – Random Dev Mar 29 '15 at 17:42
  • @dfeuer well I guess you are right - the big question is: is this a good thing? - but I guess this is not the right place for such discussions and you already got my upvote too - so have a nice day – Random Dev Mar 29 '15 at 18:28
  • 1
    @CarstenKönig Indeed, I think I'm more likely to use the plain version in real code. The step from point-free to point-less can be very short. – chi Mar 29 '15 at 18:35
  • Thanks, I'm relatively new to Haskell and its control structures, so I'll take a look at `Control.Arrow` now. – Tom Galvin Mar 29 '15 at 19:18
  • @Quackmatic If you are new, keep in mind that arrows are quite abstract. You may want to look at functors and/or monads first. – chi Mar 29 '15 at 21:57
7

If you don't want to use Control.Arrow, you can always use Applicative:

withSelf f = (,) <$> id <*> f

Many people will probably actually understand this immediately, but for something so simple it's pretty silly.

Edit

As pointed out in a comment, this can be written even more briefly as

withSelf = ((,) <*>)

This astonished me at first, but it's actually very simple: for (->) r, fmap = (.), so the <$> id is completely redundant!

Community
  • 1
  • 1
dfeuer
  • 48,079
  • 5
  • 63
  • 167