28

I found defining the following

(%)  = flip fmap

I can write code like this:

readFile "/etc/passwd" % lines % filter (not . null)

To me it makes more sense than the alternative:

filter (not . null) <$> lines <$> readFile "/etc/passwd"

Obviously, it's just a matter of order.

Does anyone else do this? Is there a valid reason not to write code like this?

Chris Stryczynski
  • 30,145
  • 48
  • 175
  • 286
James
  • 622
  • 6
  • 6

5 Answers5

12
(<&>) :: Functor f => f a -> (a -> b) -> f b 

Now available from Data.Functor in base.

https://hackage.haskell.org/package/base-4.12.0.0/docs/Data-Functor.html#v:-60--38--62-

Chris Stryczynski
  • 30,145
  • 48
  • 175
  • 286
10

Your operator (%) is exactly the operator (<&>) from the lens package.

It can be imported with:

import Control.Lens.Operators ((<&>))
Chris Stryczynski
  • 30,145
  • 48
  • 175
  • 286
Bakuriu
  • 98,325
  • 22
  • 197
  • 231
6

There is a similar function for the Applicative type class called <**>; it's a perfectly reasonable thing to want or use for Functor as well. Unfortunately, the semantics are a bit different for <**>, so it can't be directly widened to apply to Functor as well.

Matthias Braun
  • 32,039
  • 22
  • 142
  • 171
bdonlan
  • 224,562
  • 31
  • 268
  • 324
4
-- (.) is to (<$>) as flip (.) is to your (%).  

I usually define (&) = flip (.) and it's just like your example, you can apply function composition backwords. Allows for easier to understand points-free code in my opinion.

codebliss
  • 426
  • 4
  • 10
1

Personally I wouldn't use such an operators because then I have to learn two orders in which to read programs.

Martijn
  • 6,713
  • 3
  • 31
  • 38
  • 1
    Not sure I find this argument compelling enough, but it's an interesting point of view, so +1. Out of curiosity: do you prefer `=<<` over `>>=` for that same reason? – Stephan202 Nov 05 '09 at 08:52
  • 1
    I never understood the previous statement. It seems to make sense using standard notation because then it's like unix piping? – codebliss Nov 05 '09 at 20:16
  • 6
    I prefer =<< to >>= because the form has a clear interpretation in terms of the Kleisli category of your monad which can be inverted to give an understandable definition for comonads. – Edward Kmett Nov 05 '09 at 20:37
  • Stephan: that said your argument seems I'll posed. Preferring >>= to =<< would be more appropriate as you are given the former and the other is derived. I realize you were after the argument order though. – Edward Kmett Nov 05 '09 at 20:40
  • I disagree. One *already* has to reverse the narration flow in deep function compositions (point-free style most notably), to be able to construe the data flow of the code. At the same time, `>>=` does lead to code flow which matches data flow. These together can easily lead to code lines like this: `action1 >>= action3 . action2 >>= action4`, where the reader has to *reverse his reading order multiple times in a line* to be able to understand the data flow pipeline. Flipped function composition will be helpful in this case. – ulidtko Dec 24 '14 at 16:54