Можно создать дубликат:
Haskell: difference between . (dot) and $ (dollar sign)
Я понимаю, что "$" связывает выражение, как "f1 (f2 х)" в более простой форме «f1 $ f2 Икс". Как «f1.f2 x» отличается от этого?
Можно создать дубликат:
Haskell: difference between . (dot) and $ (dollar sign)
Я понимаю, что "$" связывает выражение, как "f1 (f2 х)" в более простой форме «f1 $ f2 Икс". Как «f1.f2 x» отличается от этого?
Хорошо, f1 . f2 x
- это состав f1
и f2 x
. Вероятно, вы имеете в виду (f1 . f2) x
или, что эквивалентно, f1 . f2 $ x
; т.е. состав f1
и f2
, примененный к x
.
Ответ можно найти, посмотрев на типы:
($) :: (a -> b) -> a -> b
(.) :: (b -> c) -> (a -> b) -> a -> c
Просто ($)
применяет функцию к своему аргументу, и (.)
composes двух аргументов. Две цепи
f . g . h $ x
и
f $ g $ h $ x
эквивалентны; первый из них, как правило, предпочтительнее, потому что легче реорганизовать композицию в свою функцию с помощью вырезания и вставки, но это не универсальное предпочтение. Это также немного ниже визуального шума.
Действительно, ($)
идентичен id
, функция идентификации; он просто возвращает функцию, которую она дала. Это полезно только из-за очень низкого приоритета оператора (самого низкого, фактически), предоставленного ему.
Ни ($)
, ни (.)
не делают ничего особенного, чтобы «связать выражение». Они просто операторы, как и все остальные. Все, что вам нужно знать, это то, что они определены, и каковы их исправления. Для первого:
infixr 0 $
f $ x = f x
Таким образом, это функциональное приложение с очень низким приоритетом и право-ассоциативностью. Поэтому, если у вас есть f x $ g y z
, это означает (f x) (g y z)
, что эквивалентно f x (g y z)
. Он используется, чтобы избежать скобок, в основном.
Для второго:
infixr 9 .
(.) f g x = f (g x)
Это выглядит похоже на первое, но (.)
работает на двух функций, а не функции и аргумента, и имеет очень высокий приоритет. Поэтому, если у вас есть (f x . g y) z
, это означает (f x) ((g y) z)
, что эквивалентно f x (g y z)
.
Главное отличие состоит в том, что с (.)
вы можете связать множество функций вместе, например f1 . f2 . f3
, тогда как с ($)
вы можете применять только другие функции к результату.Поэтому в выражении типа f x $ g y $ h z
, если вы решите заменить одно значение z
на весь список значений, вы не можете просто написать map (f x $ g y $ h) zs
, потому что в выражениях, заключенных в скобки, нет ничего для функций. Если вы вместо этого напишите что-то вроде f x . g y . h $ z
, вы можете удалить только окончательное приложение-приложение и получить map (f x . g y . h) zs
, и он будет работать.
Я бы сказал, что '($)' также полезно (или, по крайней мере, прохладно) для создания таких вещей, как 'map ($ 3) [(+5), (* 2), (subtract 4)]' –
Я никогда не думал об этом раньше, но вы, вероятно, можете сделать «map (\' id \ '3) [(+5), (* 2), (subtract 4)]' тоже! :) – Rotsor