2010-06-26 8 views
30

Я пытаюсь проверить что-то для себя о приоритете оператора и функции в Haskell. Например, следующий кодОператор Haskell против приоритета функции

list = map foo $ xs 

можно переписать в виде

list = (map foo) $ (xs) 

и в конечном итоге будет

list = map foo xs 

Мой вопрос раньше, почему первая формулировка не будет переписать в виде

list = (map foo $) xs 

, поскольку приоритет функции всегда выше приоритета оператора, но я думаю, что нашел ответ: операторам просто не разрешено быть аргументами функций (за исключением, конечно, если вы окружите их круглыми скобками). Это правильно? Если это так, мне показалось странным, что в RWH не упоминается об этом механизме/правилах или не узнаете вас в Haskell или в любом другом месте, которое я искал. Поэтому, если вы знаете место, где указано правило, обратитесь к нему.

- изменить: Спасибо за ваши быстрые ответы. Я думаю, что моя путаница возникла из-за того, что оператор-литерал каким-то образом оценит что-то, что может быть использовано функцией в качестве аргумента. Это помогло мне вспомнить, что оператор инфикса можно механически перевести на префиксные функции. Делая это первая формулировка урожайности

($) (map foo) (xs) 

, где нет никаких сомнений в том, что ($) есть функция потребления, и так как обе формулировки эквивалентны, то $ буквальным в первой формулировке не может потребляться по карте.

ответ

20

Вы правы. Это правило является частью синтаксиса Haskell, определяемого Haskell Report. В частности, обратите внимание в разделе 3 «Выражения», что аргумент функции приложения (fexp) должен быть aexp. Aexp позволяет операторам как часть разделов, так и внутри выражения в скобках, но не голые операторы.

В map foo $ xs синтаксис Haskell означает, что это анализируется как два выражения, которые применяются к двоичному оператору $. Как отмечает sepp2k, синтаксис (map foo $) является левым разделом и имеет другое значение.

Должен признаться, я никогда не думал об этом и на самом деле должен был найти его в отчете, чтобы узнать, почему у операторов есть поведение, которое они выполняют.

8

Операторы могут передаваться как аргументы функции, если вы окружите их скобкой (то есть map foo ($) xs, которая действительно будет передана как (map foo ($)) xs). Однако, если вы не окружите их круглыми скобками, вы правы, что их нельзя передать в качестве аргумента (или назначить переменным).

отметить также, что синтаксис (someValue $) (где $ может быть любой оператор) на самом деле означает что-то другое: это эквивалентно \x -> someValue $ x, т.е. он частично применяет оператор к его левого операнда (который в случае $ является Noop конечно). Аналогично ($ x) частично применяет оператор к правому операнду. Таким образом, map ($ x) [f, g, h] будет оцениваться до [f x, g x, h x].

27

Во-первых, приложение (пробелы) является оператором с наивысшим приоритетом.

Во-вторых, в Haskell нет никакого различия между операторами и функциями, кроме того, что по умолчанию операторы infix, а функции - нет. Вы можете преобразовать функции инфиксные с

обратными кавычками
2 `f` x 

и преобразованием операторов префикса скобками:

(+) 2 3 

Итак, ваш вопрос немного запуталось.

Теперь специфические функции и операторы будут объявлены приоритет, который вы можете найти в GHCi с «: информация»:

Prelude> :info ($) 
($) :: (a -> b) -> a -> b -- Defined in GHC.Base 

infixr 0 $ 

class (Eq a, Show a) => Num a where 
    (+) :: a -> a -> a 

infixl 6 + 

Показаны как приоритет и ассоциативность.

+0

спасибо. После прочтения вашего ответа, когда вы говорите, что мой вопрос немного смущен, я беру его, чтобы понять, что мое упоминание о «приоритете функции» неверно, и что функции сами по себе не имеют никакого приоритета, а скорее могут рассматриваться как аргументы оператору приложения, пробелы. Это верно? Я до сих пор не совсем понимаю, как инфиксные операторы вписываются в это. Я отредактировал свой вопрос, чтобы подумать, как я могу лучше подумать об этом. Правильно ли это понимание? – Boris

+0

Нет, не совсем. Функции и операторы неразличимы в Haskell. Они могут иметь разные уровни приоритета, указанные пользователем. –

+3

Хорошо. Я все еще пытаюсь выяснить общее правило, которое приводит к списку = (map foo) $ (xs) вместо list = (map foo $) xs - что я знаю - это раздел. Можно ли сказать, что при принятии решения, для данного выражения, какие аргументы принадлежат тем функциям и операторам, функции потребляют - начиная с левой стороны - все аргументы, которые они могут, до тех пор, пока они не достигнут оператора.После этого операторы используют свои аргументы в соответствии с их приоритетом и ассоциативностью (это немного расплывчато, но, надеюсь, вы понимаете). Извините, если это кажется очевидным, но мне это никогда не было ясно. – Boris

10

Разница заключается в том, что операторы инфиксные объекты помещаются между их аргументами, так что

list = map foo $ xs 

можно переписать в виде префикса в

list = ($) (map foo) xs 

, который, по определению $ оператора, является просто

list = (map foo) xs 
9

В дополнение к информации, предоставленной другими ответами, обратите внимание, что разные операторы могут иметь разные приоритеты над другими операторами, а также быть левыми/правыми или неассоциативными. Вы можете найти эти свойства для операторов Prelude в Haskell 98 Report fixity section.

 
+--------+----------------------+-----------------------+-------------------+ 
| Prec- | Left associative | Non-associative | Right associative | 
| edence |  operators  |  operators  | operators  | 
+--------+----------------------+-----------------------+-------------------+ 
| 9  | !!     |      | .     | 
| 8  |      |      | ^, ^^, **   | 
| 7  | *, /, `div`,   |      |     | 
|  | `mod`, `rem`, `quot` |      |     | 
| 6  | +, -     |      |     | 
| 5  |      |      | :, ++    | 
| 4  |      | ==, /=, <, <=, >, >=, |     | 
|  |      | `elem`, `notElem`  |     | 
| 3  |      |      | &&    | 
| 2  |      |      | ||    | 
| 1  | >>, >>=    |      |     | 
| 0  |      |      | $, $!, `seq`  | 
+--------+----------------------+-----------------------+-------------------+ 

Любой оператор отсутствует заявление фиксированности предполагается левоассоциативно с приоритетом 9.

Помните, что применение функции имеет наивысший приоритет (думаю старшинства 10 по сравнению с другими старшинства в таблице) [1].

+0

Как получилось 'f g. h' эквивалентно 'f (g.h)'? Означает ли это, что приоритет приложения приложения меньше или совпадает с приоритетом композиции? – CMCDragonkai

+0

@CMCDragonkai Я обновил ответ с приоритетом приложения приложения. 'f g. h' эквивалентно '(f g). h', поскольку функция приложения имеет более высокий приоритет, чем любой приоритет оператора (включая состав функции). – mucaho

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

  • Нет связанных вопросов^_^