How does one combine using $
and point-free style?
A clear example is the following utility function:
times :: Int -> [a] -> [a]
t
In Haskell, function composition is associative¹:
f . g . h == (f . g) . h == f . (g . h)
Any infix operator is just a good ol' function:
2 + 3 == (+) 2 3
f 2 3 = 2 `f` 3
A composition operator is just a binary function too, a higher-order one, it accepts 2 functions and returns a function:
(.) :: (b -> c) -> (a -> b) -> (a -> c)
Therefore any composition operator can be rewritten as such:
f . g == (.) f g
f . g . h == (f . g) . h == ((.) f g) . h == (.) ((.) f g) h
f . g . h == f . (g . h) == f . ((.) g h) == (.) f ((.) g h)
Every function in Haskell can be partially applied due to currying by default. Infix operators can be partially applied in a very concise way, using sections:
(-) == (\x y -> x - y)
(2-) == (-) 2 == (\y -> 2 - y)
(-2) == flip (-) 2 == (\x -> (-) x 2) == (\x -> x - 2)
(2-) 3 == -1
(-2) 3 == 1
As composition operator is just an ordinary binary function, you can use it in sections too:
f . g == (.) f g == (f.) g == (.g) f
Another interesting binary operator is $, which is just function application:
f x == f $ x
f x y z == (((f x) y) z) == f x y z
f(g(h x)) == f $ g $ h $ x == f . g . h $ x == (f . g . h) x
With this knowledge, how do I transform concat $ replicate n xs
into point-free style?
times n xs = concat $ replicate n xs
times n xs = concat $ (replicate n) xs
times n xs = concat $ replicate n $ xs
times n xs = concat . replicate n $ xs
times n = concat . replicate n
times n = (.) concat (replicate n)
times n = (concat.) (replicate n) -- concat is 1st arg to (.)
times n = (concat.) $ replicate n
times n = (concat.) . replicate $ n
times = (concat.) . replicate
¹Haskell is based on category theory. A category in category theory consists of 3 things: some objects, some morphisms, and a notion of composition of morphisms. Every morphism connects a source object with a target object, one-way. Category theory requires composition of morphisms to be associative. A category that is used in Haskell is called Hask, whose objects are types and whose morphisms are functions. A function f :: Int -> String
is a morphism that connects object Int
to object String
. Therefore category theory requires Haskell's function compositions to be associative.