Random Operators: How to Make Friends and Influence Your Co-workers

If you were to ask me what language does operator overloading right, my unqualified answer would be Haskell. Unlike many languages, such as Rust or C++, operators aren’t these special things. They are just functions. Also, unlike many languages, you can define any arbitrary operator.

Now, ask me what I think is a major issue with Haskell. Do it. I dare you.

Well, if you insist…

A major issue I have with Haskell is that there are too many operators! Hundreds in base, and every library author thinks it’s ok to create hundreds more! Unfortunately, such is life; might as well get used to it.

There are two operators in particular that are quite prolific, and I think worthy of further discussion: . and $.

Function Composition

Here is the type of . :

(.) :: (b -> c) -> (a -> b) -> a -> c

. is the function composition operator. Take a function f :: a -> b and a function g :: b -> c, you can create a function fg :: a -> c:

fg :: a -> c fg = g . f

You can chain these together too. Let h :: c -> d, i :: d -> e, and just for fun j :: e -> a:

funWithCategories :: a -> a funWithCategories = j . i . h . g . f

Try it with your friends! They’ll love you!

I know, it was hard for me to write too, but I’ll be darned if it doesn’t look good! Just replace the . with “after”, and read it out loud:

"j after i after h after g after f"

Or, if you prefer to look at code:

funWithCategories :: a -> a funWithCategories a = j (i (h (g (f a))))

… or in C:

a fun_with_categories(a input) { return j(i(h(g(f(input))))); }

Function Application

Now, let’s talk about $ the function application operator. Here is the type of $ :

($) :: (a -> b) -> a -> b

Basically it applied its right hand side argument to the left hand side function. Thus show 1 is the same thing as show $ 1. However, there’s a twist. Function application in Haskell is the highest precedence thing that can happen. This means that we often have to use a lot of parenthesis to make our code compile. Say I wanted to convert the output of 2 + 2. This won’t work:

Prelude> show 2 + 2 <interactive>:25:8: No instance for (Num String) arising from a use of ‘+’ In the expression: show 2 + 2 In an equation for ‘it’: it = show 2 + 2

What actuall happened was:

(show 2) + 2

…and that’s just silly. To make this code compile, we have to add parenthesis:

Prelude> show (2 + 2) "4"

which is kind of annoying. However, we can use $ to eliminate these parenthesis!

Prelude> show $ 2 + 2 "4"

The function application operator has a precedence of 0, so the addition happens first! It has a right fixity so you can chain it!

funWithOperators :: a -> a funWithOperators a = j $ i $ h $ g $ f a

Hey, I’ve Seen That Function Before!

If this looks familiar to you, then you’ve been paying attention!

($) :: (a -> b) -> a -> b (.) :: (b -> c) -> (a -> b) -> a -> c

If you chop off the first argument of . and squint, they kind of look the same. Logically, they can often be used interchangeably, however you will end up using some parenthesis with ..

My advice:

Use $ if you’re trying to produce a value for use right now. If you find yourself doing something like this:

show (show ( show( show "catcatcatcat")))

… then change it to this and save yourself the hassle of counting parenthesis:

show $ show $ show $ show "catcatcatcat"

Use . when you’re trying to make a function. If you find yourself doing something like this:

showWith :: (Show a) => (a -> String) -> a -> String showWith = -- stuff shower :: (Show a) => a -> String shower a = show $ show $ show $ show a showWith shower "catcatcatcat"

… then you can avoid defining shower like so:

showWith (show . show . show . show) "catcatcatcat"

Trackbacks / Pingbacks

  1. Operator Overloading in C++ | Doing My Programming... - April 7, 2016

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: