Skip to main content

Operators of Interest

Todo

Composition (.)

The . function for composition:

f x = x + 3
square x = x ^ 2

{- could be done this way -}
squareOfF x = square (f x)
fOfSquare x = f (square x)

-- or this way
squareOfF x = (square . f) x
fOfSquare x = (f . square) x

Futhermore, as functions, you can do this:

squareOfF x = (square . f) x
-- is
squareOfF = square . f -- just drop the `x` from both sides!

More on (.)

From a question I asked in r/haskell,

data AdventureOptions = AdventureOptions {unOptions :: String}

-- unOptions :: AdventureOptions -> String
-- pure :: a -> IO a
-- pure . unOptions :: AdventureOptions -> IO String

main = parse >>= (pure . unOptions) >>= (\s -> putStrLn $ "You chose: '" ++ s ++ "'.")
-- or
main = parse >>= (\a -> putStrLn $ "You chose: '" ++ unOptions a ++ "'.")

Another look:

(f . g) x = f (g x)
(f . g) = \x -> f (g x) -- the `x` gets "pulled" into the lambda
-- and you can η-reduce even further.

Dots '&' Dollars

The "dot" operator is actually function composition, used for chaining functions:

example :: [Integer] -> [Integer]
example =
sort
. filter (<100) -- note the spaces (both leading and following)
. map (*10)

The . operator gets explored more under Pointfree Programming.

The $ operator is use for function application. It takes the right side of the operator and applies it to the left side which helps with nested functions:

foo $ bar $ baz bin
-- is the same as
foo (bar (baz bin))

$ has the lowest possible precedence for any infix operator:

:info ($)
--λ ($) :: (a -> b) -> a -> b -- Defined in ‘GHC.Base’
--λ infixr 0 $ -- which tells us it has 0 precedence

You can look at the $ as an open parenthesis with an implicit close at the end of the expression:

last $ take 10 [1..]
-- is the same as
last (take 10 [1..])

The & does the reverse of $:

bin & baz & bar & foo
-- is the same as
foo $ bar $ baz bin

Comparisons between all three (from Wiwinwhlh):

ex1 = f1 . f2 . f3 . f4 $ input -- with ($)
ex1 = input & f1 . f2 . f3 . f4 -- with (&)
ex1 = (f1 . f2 . f3 . f4) input -- with explicit parens

Odd Bits

<$> is a synonym for fmap:

(*2) <$> [1,2,3]
-- [2,4,6]

even <$> (2,2)
-- (2,True)

Use parentheses to turn an infix operator into a prefix. These are equivalent:

4 + 9 == 13
(==) (4 + 9) 13
--λ True

Likewise, you can turn a function "prefix" into an infix using backticks:

div 100 9
-- can be replaced by
100 `div` 9

</> is the file separator operator:

"/directory" </> "file.ext" == "/directory/file.ext"