Reputation: 3391
Given this definition of a function f
:
f :: [Int] -> [Int]
f [] = []
f (x:xs) = x:[]
I would assume that a call such as
f [1]
would not match, because the pattern (x:xs)
only matches, if there are more elements xs
after the x
in the list, which is not the case for the list [1]
. Or is it?
Upvotes: 2
Views: 2687
Reputation: 477318
If you write [x]
, a list with one element, this is short for (x : [])
, or even more verbose (:) x []
. So it is a "cons" ((:)
) with x
as element, and the empty list as tail.
So your function f (x:xs)
will indeed match a list with one (or more) elements. For a list with one element, x
will be the element, and xs
an empty list.
would not match, because the pattern
(x:xs)
only matches, if there are more elementsxs
after thex
in the list, which is not the case for the list[1]
.
No the (x:xs)
matches with every non-empty list, with x
the first element of the list, and xs
a (possibly empty) list of remaining elements.
If you want to match only lists with for example two or more elements. You can match this with:
-- two or more elements
f (x1 : x2 : xs) = …
Here x1
and x2
will match the first and second item of the list respectively, and xs
is a list that contains the remaining elements.
EDIT: to answer your comments:
I wonder why my function definition does even compile in the first place, because the function type is
[Int] -> [Int]
, so if I give it the empty list, then that is not[Int]
as a result, is it?
The empty list []
is one of the data constructors of the [a]
type, so that means that []
has type [] :: [a]
. It can match the type variable a
with Int
, and thus []
can have type [] :: [Int]
.
Second then, how to I match a list with exactly two elements?
[a, b]
?
You can match such list with:
f (a : b : []) = …
or you can match it with:
f [a, b] = …
The two are equivalent. [a, b]
is syntactical sugar: it is replaced by the compiler to (a : b : [])
, but for humans, it is of course more convenient to work with [a, b]
.
Upvotes: 10