Оператор $
$
является , а не частью синтаксиса Haskell. Это встроенный оператор ($) :: (a -> b) -> a -> b
, и оператор определяется как inxfixr 0
с реализацией:
($) :: (a -> b) -> a -> b
($) f x = f x
Таким образом, он принимает в качестве входных данных функцию f
и значение x
и возвращает f
, примененную к x
. Так как он имеет приоритет 0
, это означает, что он связывается очень низко, и, следовательно, если вы напишите
f . g $ x + 2
вы на самом деле пишете:
($) ((.) f g) ((+) x 2)
, которая является многословной формой:
((.) f g) ((+) x 2)
или
(f . g) (x + 2)
Так что его можно использовать как " трюк ", чтобы заставить Haskell сам добавлять скобки. Поскольку он является оператором, а не частью синтаксиса, он не работает в других местах, таких как подписи типов, шаблоны, производные предложения.
Оператор, конечно, служит и другим целям. Например, мы можем использовать его в других функциях высшего порядка (например, zipWith ($)
, который принимает список функций [f1, f2, ...]
и список значений [x1, x2, ...]
и возвращает список [f1 x1, f2 x2, ...]
).
Минимизация количества скобок
Однако мы можем минимизировать количество скобок. Например, предложение deriving
не требует скобок, если вы выводите класс single type, поэтому мы можем написать его следующим образом:
data Vector = Vector XY XY deriving Show
data XY = XY (Float , Float) deriving Show
Кроме того, в объявлении функции вы распаковываете кортежи, но затем вы перепаковываете элементы кортежа обратно в кортеж, который в основном одинаков. Мы можем уменьшить выражение (и уменьшить объем распаковки и повторной упаковки), связавшись с содержимым конструктора XY
вместо этого:
vector (Vector (XY xy1) (XY xy2)) = [xy1, xy2]