1

I'm very new to Haskell, and I decided to learn it some days ago, thanks to the haskell wikibook.

I'm reading at this moment the matching pattern for lists, but I can't understand the syntax for list.

Here's an example (from the wikibook) :

doubleList :: [Integer] -> [Integer]
doubleList [] = []
doubleList (n:ns) = (2 * n) : doubleList ns

I don't understand the part (n:ns). How should I read it ?

Maxime
  • 570
  • 3
  • 18

3 Answers3

6

You can read it like this: (head:tail), so if you have [1, 2, 3] and you match it with (x:xs), then x will be bound to the first element in the list, 1, and xs will be bound to the rest of the list, in this case [2, 3].

Jorge Israel Peña
  • 36,800
  • 16
  • 93
  • 123
  • why do we need parents when list pattern matching? Why simple `foo x:xs = undefined` leads us to `error: Parse error in pattern: foo` – aryndin Jul 15 '18 at 14:31
  • ok, already found https://stackoverflow.com/questions/2191294/what-do-the-parentheses-signify-in-xxs-when-pattern-matching – aryndin Jul 15 '18 at 14:33
3

(:) is an operator with type a->[a]->[a]. This means that it takes an item, and a list of those items, and returns another list of the same items. The output list is formed by prepending the input item to the input list.

Here is how you can use it

1:[2,3]

will return

[1,2,3]

Because the (:) appears on the left hand side of the definition, in your case, you are pattern matching, and the operator is being used to deconstruct the value, rather than build it.

For example, if we have

func (first:rest) = ....

and call it like this

func [1,2,3]

the following values would be assigned

first=1 --notice, this is type a
rest=[2,3] --notice, this is type [a]
jamshidh
  • 12,002
  • 17
  • 31
  • Thanks for your answer. So the (:) function is called cons, isn't it ? You say cons behaves differently when it is on the left on the declaration, is it a language feature ? – Maxime Dec 12 '14 at 19:04
  • @MaximeB.- yes it is. Actaully everything on the left of a definition behaves differently than the right (and it is very much a feature). Left is for pattern matching, right is for output. You can think of it a bit like a regex pattern match `///`. – jamshidh Dec 12 '14 at 19:14
  • 1
    note that `:` is a constructor, not a function. You can "unapply" constructors by pattern matching on them, but you can't unapply functions in the same way. – rampion Dec 12 '14 at 20:37
  • 1
    @rampion- Just to confuse matters more, I have to point out that constuctors are functions also.... – jamshidh Dec 12 '14 at 21:18
3

Another tip that might help you understand is by looking at the definition of the list data type:

data [] a = [] | a : ([] a)

Note that Haskell makes special syntax rules just for the list type, normally [] is not a valid constructor. This definition is equivalent to

data List a = Empty | Cons a (List a)

Where

[] = Empty
(:) = Cons

You would pattern match on this as

doubleList :: List Int -> List Int
doubleList Empty = Empty
doubleList (Cons n ns) = Cons (2 * n) (doubleList ns)

If written using infix form:

doubleList (n `Cons` ns) = (2 * n) `Cons` doubleList ns

So now hopefully you can see the parallels between the two definitions. Haskell also provides the special syntax rule that

[1, 2, 3, 4] = 1:2:3:4:[]

Since the former is much easier to write and read. In fact, whenever you have a list literal like [1, 2, 3, 4] in your code, the compiler first converts it to 1:2:3:4:[] before converting your code into an executable.

bheklilr
  • 53,530
  • 6
  • 107
  • 163