В Haskell композиция функций ассоциативна¹:
f . g . h == (f . g) . h == f . (g . h)
Любой инфиксный оператор - это просто хорошая старая функция:
2 + 3 == (+) 2 3
f 2 3 = 2 `f` 3
A оператор композиции тоже просто двоичная функция, высшего порядка , она принимает 2 функции и возвращает функцию:
(.) :: (b -> c) -> (a -> b) -> (a -> c)
Поэтому любой оператор композиции может быть переписан так:
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)
Каждая функция в Haskell может быть частично применена из-за curry по умолчанию. Инфиксные операторы могут быть частично применены очень кратким способом, используя секции :
(-) == (\x y -> x - y)
(2-) == (-) 2 == (\y -> 2 - y)
(-2) == flip (-) 2 == (\x -> (-) x 2) == (\x -> x - 2)
(2-) 3 == -1
(-2) 3 == 1
Так как оператор композиции - это обычная бинарная функция, вы также можете использовать ее в секциях:
f . g == (.) f g == (f.) g == (.g) f
Еще один интересный бинарный оператор - $ , который является просто приложением функции:
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
С этим знанием, как мне преобразовать 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 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 основан на теории категорий . Категория в теории категорий состоит из 3 вещей: некоторые объекты , некоторые морфизмы и понятие композиции морфизмов. Каждый морфизм соединяет исходный объект с целевым объектом , в одну сторону. Теория категорий требует, чтобы композиция морфизмов была ассоциативной. Категория, которая используется в Haskell, называется Hask , чьи объекты являются типами, а морфизмы - функциями. Функция f :: Int -> String
- это морфизм, который связывает объект Int
с объектом String
. Поэтому теория категорий требует, чтобы композиции функций Хаскелла были ассоциативными.