Что круглые скобки показывают в (x:xs) когда сопоставление с образцом?

когда Вы разделяете список с помощью x:xs синтаксис, почему он перенесен в круглые скобки? каково значение круглых скобок? почему не [x:xs] или просто x:xs?

26
задан Don Stewart 18 April 2011 в 22:00
поделиться

5 ответов

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

приложение-функция связывает более жестко, чем любой инфиксный оператор.

Запишите это в свой мозг огненными буквами.

Пример:

length [] = 0
length (x:xs) = 1 + length xs

Если скобки опущены, компилятор подумает, что у вас есть аргумент x , за которым следует неверно размещенный инфиксный оператор, и будет горько жаловаться. С другой стороны, это нормально

length l = case l of [] -> 0
                     x:xs -> 1 + length xs

. В этом случае ни x , ни xs не могут рассматриваться как часть приложения-функции, поэтому скобки не нужны.

Обратите внимание, что то же замечательное правило , приложение функции связывает более жестко, чем любой инфиксный оператор , это то, что позволяет нам записывать length xs в 1 + length xs без каких-либо круглые скобки. Правило инфиксов дает, а правило инфиксов отнимает.

45
ответ дан 28 November 2019 в 06:35
поделиться

Вы просто используете оператор cons : , который имеет низкий приоритет. Скобки нужны, чтобы все оставалось правильно.

И вы не используете [x: xs] , потому что это будет соответствовать списку, единственным элементом которого является список с головой x и хвостом xs ].

14
ответ дан 28 November 2019 в 06:35
поделиться

Это связано с синтаксическим анализом.

Помните, двоеточие: - это просто конструктор, написанный с использованием синтаксиса оператора. Так что функция, подобная

foo [] = 0
foo (x:xs) = x + foo xs

, также может быть записана как

foo [] = 0
foo ((:) x xs) = x + foo xs

. Если вы опустите скобку в этой последней строке, ее будет очень трудно разобрать!

2
ответ дан 28 November 2019 в 06:35
поделиться

: - это конструктор данных, как и любое другое сопоставление с шаблоном, но с написанным инфиксом. Круглые скобки здесь исключительно из-за приоритета инфиксов; на самом деле они не требуются и могут быть безопасно опущены, если это разрешено правилами приоритета. Например:

> let (_, a:_) = (1, [2, 3, 4]) in a
2
> let a:_ = "xyzzy"
'x'
> case [1, 2, 3] of; a:b -> a; otherwise -> 0;
1

Интересно, что это, похоже, не работает в заголовке лямбды. Не знаю почему.

Как всегда, оператор "сопоставления" связывает более жестко, чем что-либо еще, поэтому чаще всего разделители необходимы, но на самом деле они не часть сопоставления с образцом - иначе вы не t уметь использовать шаблоны вроде (x: y: zs) вместо (x: (y: zs)) .

1
ответ дан 28 November 2019 в 06:35
поделиться

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

data Foo = Bar | Baz Int

f :: Foo -> Int
f Bar     = 1
f (Baz x) = x - 1

Конструкторы, состоящие из одного слова, соответствуют как есть. Но составные конструкторы должны быть окружены скобками, чтобы избежать двусмысленности. Если мы пропускаем скобки, это выглядит как сопоставление двух независимых аргументов:

f Baz x = x - 1

Итак, поскольку (:) составной, он должен быть в скобках. Пропуск скобок для Bar - это своего рода синтаксический сахар.

ОБНОВЛЕНИЕ: Я понял, что (как отметила Сикора) это следствие приоритета операторов. Это проясняет мои предположения. Приложение функции (которое является просто пробелом между функцией и аргументом) имеет наивысший приоритет. Другие, включая (:), имеют более низкий приоритет. Итак, f x: xs следует интерпретировать как ((:) (f x)) xs , что, по-видимому, не то, что нам нужно. В то время как f (x: xs) интерпретируется как f , применяемый к x: xs , который, в свою очередь, (:) применяется к x и xs .

3
ответ дан 28 November 2019 в 06:35
поделиться
Другие вопросы по тегам:

Похожие вопросы: