2012-01-13 2 views

ответ

7

Хорошо, 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, функция идентификации; он просто возвращает функцию, которую она дала. Это полезно только из-за очень низкого приоритета оператора (самого низкого, фактически), предоставленного ему.

+1

Я бы сказал, что '($)' также полезно (или, по крайней мере, прохладно) для создания таких вещей, как 'map ($ 3) [(+5), (* 2), (subtract 4)]' –

+0

Я никогда не думал об этом раньше, но вы, вероятно, можете сделать «map (\' id \ '3) [(+5), (* 2), (subtract 4)]' тоже! :) – Rotsor

6

Ни ($), ни (.) не делают ничего особенного, чтобы «связать выражение». Они просто операторы, как и все остальные. Все, что вам нужно знать, это то, что они определены, и каковы их исправления. Для первого:

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, и он будет работать.

Смежные вопросы