tags:

views:

200

answers:

5

when you split a list using x:xs syntax why is it wrapped in a parentheses? what is the significance of the parentheses? why not [x:xs] or just x:xs?

+11  A: 

You're simply using the cons operator :, which has low precedence. Parentheses are needed so that things stay right.

And you don't use [x:xs], because that would match a list whose only element is a list with head x and tail xs.

sykora
I had never tried that specific `[x:xs]` pattern, but of course you're right; it matches a singleton list on the top level. The desugared notation of the pattern would be: `((x:xs):[])`.
Tom Lokhorst
+2  A: 

I don't know exact answer, but I guess that is due to what can be matched in patterns. Only constructors can be matched. Constructors can be of single word or composite. Look at the next code:

data Foo = Bar | Baz Int

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

Single word constructors match as is. But composite constructors must be surrounded with parens in order to avoid ambiguity. If we skip parens it looks like matching against two independent arguments:

f Baz x = x - 1

So, as (:) is composite it must be in parens. Skipping parens for Bar is a kind of syntactic sugar.

UPDATE: I realized that (as sykora noted) it is a consequence of operator precedence. It clarifies my assumptions. Function application (which is just space between function and argument) has highest precedence. Others including (:) have lower precedence. So f x:xs is to be interpreted as ((:) (f x)) xs that is presumably not what we need. While f (x:xs) is interpreted as f applied to x:xs which is in turn (:) applied to x and xs.

Rorick
+2  A: 

It's to do with parsing.

Remember, the colon : is just a constructor that's written with operator syntax. So a function like

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

could also be written as

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

If you drop the parenthesis in that last line, it becomes very hard to parse!

yatima2975
+1  A: 

: is a data constructor, like any other pattern match, but written infix. The parentheses are purely there because of infix precedence; they're actually not required and can be safely omitted when precedence rules allow. For instance:

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

Interestingly, that doesn't seem to work in the head of a lambda. Not sure why.

As always, the "juxtaposition" operator binds tighter than anything else, so more often than not the delimiters are necessary, but they're not actually part of the pattern match--otherwise you wouldn't be able to use patterns like (x:y:zs) instead of (x:(y:zs)).

camccann
+12  A: 

The cons cell doesn't have to be parenthesized in every context, but in most contexts it is because

Function application binds tighter than any infix operator.

Burn this into your brain in letters of fire.

Example:

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

If parentheses were omitted the compiler would think you had an argument x followed by an ill-placed infix operator, and it would complain bitterly. On the other hand this is OK

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

In this case neither x nor xs can possibly be construed as part of a function application so no parentheses are needed.

Note that the same wonderful rule function application binds tighter than any infix operator is what allows us to write length xs in 1 + length xs without any parentheses. The infix rule giveth and the infix rule taketh away.

Norman Ramsey
+1 for letters of fire. My Haskell code stopped looking like Lisp after I internalised this rule.
Nefrubyr
+1. Love the last sentence
Wei Hu