когда вы разбиваете список с помощью синтаксиса x: xs, почему он заключен в круглые скобки? Каково значение круглых скобок? почему не [x: xs] или просто x: xs?
Что означают круглые скобки (x: xs) при сопоставлении шаблонов?
Ответ 1
Ячейка 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
без каких-либо круглых скобок. Правило инфикса дается, и правило инфикса удаляется.
Ответ 2
Вы просто используете оператор cons :
, который имеет низкий приоритет. Скобки необходимы, чтобы все оставалось в порядке.
И вы не используете [x:xs]
, потому что это будет соответствовать списку, единственным элементом которого является список с головой x
и хвостом xs
.
Ответ 3
Я не знаю точного ответа, но я думаю, это связано с тем, что можно сопоставить в шаблонах. Только конструкторы могут быть сопоставлены. Конструкторы могут быть однословными или составными. Посмотрите на следующий код:
data Foo = Bar | Baz Int
f :: Foo -> Int
f Bar = 1
f (Baz x) = x - 1
Конструкторы с одним словом соответствуют как есть. Но составные конструкторы должны быть окружены паранами, чтобы избежать двусмысленности. Если мы пропустим parens, это похоже на сопоставление с двумя независимыми аргументами:
f Baz x = x - 1
Итак, поскольку (:)
является составным, он должен быть в parens. Пропуск паров для Bar
- это своего рода синтаксический сахар.
UPDATE: я понял, что (как заметил сикора) это следствие приоритета оператора. Он разъясняет мои предположения. Функция-приложение (которое представляет собой просто пространство между функцией и аргументом) имеет наивысший приоритет. Другие, включая (:) имеют более низкий приоритет. Поэтому f x:xs
следует интерпретировать как ((:) (f x)) xs
, который, по-видимому, не тот, который нам нужен. Пока f (x:xs)
интерпретируется как f
, примененный к x:xs
, который, в свою очередь, (:)
применяется к x
и xs
.
Ответ 4
Это связано с разбором.
Помните, что двоеточие: это просто конструктор, написанный с синтаксисом оператора. Таким образом, функция типа
foo [] = 0
foo (x:xs) = x + foo xs
также может быть записано как
foo [] = 0
foo ((:) x xs) = x + foo xs
Если вы отпустите круглую скобку в этой последней строке, становится очень сложно разобрать!
Ответ 5
:
- это конструктор данных, как и любое другое совпадение шаблонов, но записанный инфикс. Скобки заключаются исключительно из-за префикса infix; они фактически не требуются и могут быть безопасно опущены, если позволяют правила приоритета. Например:
> let (_, a:_) = (1, [2, 3, 4]) in a
2
> let a:_ = "xyzzy"
'x'
> case [1, 2, 3] of; a:b -> a; otherwise -> 0;
1
Интересно, что это не работает в голове лямбда. Не знаю, почему.
Как всегда, оператор "сопоставления" привязывается сильнее, чем что-либо еще, поэтому чаще всего нужны разделители, но они фактически не являются частью совпадения шаблонов - иначе вы не сможете использовать шаблоны например (x:y:zs)
вместо (x:(y:zs))
.