В чем разница между точкой (.)
и знаком доллара ($)
?
Насколько я понимаю, они оба являются синтаксическим сахаром для того, чтобы не использовать скобки.
источник
В чем разница между точкой (.)
и знаком доллара ($)
?
Насколько я понимаю, они оба являются синтаксическим сахаром для того, чтобы не использовать скобки.
$
Оператор для избежания круглых скобок. Все, что появляется после этого, будет иметь приоритет над всем, что приходит раньше.
Например, предположим, у вас есть строка, которая гласит:
putStrLn (show (1 + 1))
Если вы хотите избавиться от этих скобок, любая из следующих строк также сделает то же самое:
putStrLn (show $ 1 + 1)
putStrLn $ show (1 + 1)
putStrLn $ show $ 1 + 1
Основная цель .
оператора не в том, чтобы избежать скобок, а в цепочке функций. Это позволяет связать вывод того, что появляется справа, с вводом того, что появляется слева. Обычно это также приводит к уменьшению скобок, но работает по-другому.
Возвращаясь к тому же примеру:
putStrLn (show (1 + 1))
(1 + 1)
не имеет ввода, и поэтому не может использоваться с .
оператором.show
может взять Int
и вернуть String
.putStrLn
могу взять String
и вернуть IO ()
.Вы можете цепочку, show
чтобы putStrLn
нравится это:
(putStrLn . show) (1 + 1)
Если вам по вкусу слишком много скобок, избавьтесь от них с помощью $
оператора:
putStrLn . show $ 1 + 1
putStrLn . show . (+1) $ 1
будет эквивалентно. Вы правы в том, что большинство (всех?) Инфиксных операторов являются функциями.map ($3)
. Я имею в виду, я в основном использую,$
чтобы избежать скобок, но это не то, для чего они здесь.map ($3)
это функция типаNum a => [(a->b)] -> [b]
. Он принимает список функций, принимающих числа, применяет 3 ко всем из них и собирает результаты.Они имеют разные типы и разные определения:
($)
предназначен для замены обычного приложения функции, но с другим приоритетом, чтобы помочь избежать скобок.(.)
для объединения двух функций, чтобы создать новую функцию.В некоторых случаях они взаимозаменяемы, но в целом это не так. Типичный пример, где они находятся:
==>
Другими словами, в цепочке
$
s все, кроме последнего, можно заменить на.
источник
x
была функция? Можете ли вы использовать.
в качестве последнего?x
в этом контексте, тогда да - но тогда «последний» будет применяться к чему-то другому, кромеx
. Если вы не подаете заявкуx
, то это ничем не отличается отx
ценности.Также обратите внимание, что
($)
это функция идентификации, специализированная для типов функций . Идентификационная функция выглядит так:Пока
($)
выглядит так:Обратите внимание, что я намеренно добавил дополнительные скобки в сигнатуру типа.
Использование
($)
обычно может быть исключено путем добавления скобок (если оператор не используется в разделе). Например:f $ g x
становитсяf (g x)
.Использование
(.)
часто немного сложнее заменить; обычно им требуется лямбда или введение явного параметра функции. Например:становится
становится
Надеюсь это поможет!
источник
($)
позволяет объединять функции без добавления скобок для управления порядком оценки:Оператор compose
(.)
создает новую функцию без указания аргументов:Приведенный выше пример, возможно, иллюстративен, но на самом деле не показывает удобство использования композиции. Вот еще одна аналогия:
Если мы используем третий раз, мы можем избежать именования с помощью лямбды:
Наконец, композиция позволяет нам избежать лямбды:
источник
Краткая и сладкая версия:
($)
вызывает функцию, которая является ее левым аргументом для значения, которое является его правым аргументом.(.)
Составляет функцию, которая является ее левым аргументом функции, которая является ее правым аргументом.источник
Одно приложение, которое полезно и заняло у меня некоторое время, чтобы разобраться из очень короткого описания, которое вы изучили :
и заключение в скобки правой части выражения, содержащего инфиксный оператор, преобразует его в префиксную функцию, которую можно написать
($ 3) (4+)
аналогично(++", world") "hello"
.Зачем кому-то это делать? Для списков функций, например. Обе:
а также:
короче
map (\x -> x ++ ", world") ...
илиmap (\f -> f 3) ...
. Очевидно, что последние варианты были бы более удобочитаемыми для большинства людей.источник
$3
без места. Если Template Haskell включен, это будет проанализировано как соединение, тогда как$ 3
всегда означает, что вы сказали. В целом, похоже, в Haskell существует тенденция «красть» биты синтаксиса, настаивая на том, что у определенных операторов есть пробелы вокруг них, которые должны рассматриваться как таковые.Они не являются синтаксическим сахаром для того, чтобы не использовать круглые скобки - они являются функциями, - вставлены, поэтому мы можем называть их операторами.
Составь
(.)
и когда его использовать.(.)
это составная функция. Такэто то же самое, что создание функции, которая передает результат своего аргумента, передаваемого
g
вf
.Используйте,
(.)
когда у вас нет доступных аргументов для передачи функциям, которые вы хотите создать.Право ассоциативного применения,
($)
и когда его использовать($)
является правоассоциативной функцией применения с низким приоритетом связывания. Так что он просто вычисляет вещи справа от него в первую очередь. Таким образом,это то же самое, что и процедурно (что важно, поскольку Haskell оценивается лениво,
f
сначала он начнет оцениваться ):или более кратко:
Используйте,
($)
когда у вас есть все переменные для оценки, прежде чем применить предыдущую функцию к результату.Мы можем увидеть это, прочитав источник для каждой функции.
Читать источник
Вот источник для
(.)
:И вот источник для
($)
:Вывод
Используйте композицию, когда вам не нужно сразу оценивать функцию. Возможно, вы хотите передать функцию, полученную в результате композиции, другой функции.
Используйте приложение, когда вы предоставляете все аргументы для полной оценки.
Так что для нашего примера было бы семантически предпочтительнее сделать
когда у нас есть
x
(точнее,g
аргументы), и делаем:когда мы не
источник
Мое правило простое (я тоже новичок):
.
если вы хотите передать параметр (вызвать функцию), и$
если еще нет параметра (составьте функцию)Это
но никогда:
источник
... или вы могли бы избежать
.
и$
конструкции, используя конвейерный :Это после того, как вы добавили в вспомогательную функцию:
источник
$
оператор на самом деле работает больше как F # 'S ,<|
чем это делает|>
, как правило , в Haskell вы бы написать вышеуказанную функцию:third xs = head $ tail $ tail $ xs
или , возможно , даже какthird = head . tail . tail
, что в F # -стиль синтаксис будет что - то вроде этого:let third = List.head << List.tail << List.tail
$
уже доступны, и это называется&
hackage.haskell.org/package/base-4.8.0.0/docs/...Отличный способ узнать больше о чем угодно (о любой функции) - помнить, что все является функцией! Эта общая мантра помогает, но в определенных случаях, таких как операторы, она помогает запомнить этот маленький трюк:
а также
Просто не забывайте использовать
:t
свободно, и заверните свои операторы в()
!источник
Я думаю, что короткий пример того, где вы будете использовать,
.
а не$
поможет прояснить ситуацию.Обратите внимание, что
times6
это функция, которая создается из композиции функций.источник
Все остальные ответы довольно хороши. Но есть важная деталь юзабилити о том, как ghc обрабатывает $, о том, что средство проверки типов ghc позволяет устанавливать типы с более высоким рангом / квантифицированными типами. Если вы посмотрите на тип,
$ id
например, вы обнаружите, что он возьмет функцию, аргумент которой сам по себе является полиморфной функцией. Такие мелочи не имеют такой же гибкости с эквивалентным оператором расстройства. (Это на самом деле заставляет задуматься, заслуживает ли $! Того же обращения или нет)источник
Самая важная часть о $ - это то, что он имеет самый низкий приоритет оператора.
Если вы введете информацию, вы увидите это:
Это говорит нам о том, что это инфиксный оператор с правой ассоциативностью, который имеет наименьший возможный приоритет. Нормальное применение функции является левоассоциативным и имеет наивысший приоритет (10). Так что $ это нечто противоположное.
Тогда мы используем его там, где обычное приложение функции или использование () не работает.
Так, например, это работает:
но это не
потому что . имеет более низкий приоритет, чем sort, а тип (sort "example") равен [Char]
Но . ожидает две функции, и нет короткого способа сделать это из-за порядка операций sort и.
источник