0

Below I've produced what I believe to be a summary of the standard $ like operators for various classes in Haskell. There's some gaps however. Following the applicative pattern, you would think those operators would be $$ and <$$> however I didn't see operators like that on Hoogle or Hayoo. Could someone fill in the gaps with the most commonly used operators for such gaps?

              | Function first           | Op   | Function second          | Op   |
----------------------------------------------------------------------------------
| Plain       | (a -> b)   -> a   -> b   | $    | a   -> (a -> b)   -> b   |      |
| Functor     | (a -> b)   -> f a -> f b | <$>  | f a -> (a -> b)   -> f b |      |
| Applicative | f (a -> b) -> f a -> f b | <*>  | f a -> f (a -> b) -> f b | <**> |
| Monad       | (a -> m b) -> m a -> m b | =<<  | m a -> (a -> m b) -> m b | >>=  |
-----------------------------------------------------------------------------------
  • 1
    taking a cue from F#, sometimes you see |> defined for a -> (a -> b) -> b. – ErikR Dec 12 '14 at 2:45
4

There isn't one sadly. People usually use the left column with . instead of separate operators. I sometimes see people use

|> :: a -> (a -> b) -> b

as a pipe line-esque operator F# and OCaml like. Generally, however, people use . instead so

 a |> f |> g

is written as

 g . f $ a

This also applies to <$>

 a |$> f |$> g

could be written as

 g . f <$> a

This is actually faster (by a factor of 2x) since <$> can be quite expensive for large collections.

  • 1
    I've seen your |> spelled as # in a few libraries. Also, I'm surprised that GHC isn't capable of rewriting a |$> f |$> g as g . f <$> a, since it's one of the functor laws. – Benjamin Hodgson Dec 12 '14 at 5:39
  • 1
    @BenjaminHodgson GHC can't assume that you actually obey the type class's laws though. Somewhere, some (probably mean) person has a codebase relying on a broken functor :/ – jozefg Mar 13 '15 at 17:55
  • @jozefg Is there an optimization setting that makes GHC assume all laws hold? Because as long as you aren't using a bad library / relying on unlawful behavior (bottoms / the exact rounding error you get from floating point math) the program should work just fine (right?). – semicolon Mar 26 '16 at 22:46
3

The lens package provides these operators:

(&) :: a -> (a -> b) -> b

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

From the lens documentation on (&):

This is the flipped version of ($), which is more common in languages like F# as (|>) where it is needed for inference. Here it is supplied for notational convenience and given a precedence that allows it to be nested inside uses of ($).

Since 7.8 (&) can be found in Data.Function too.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.