Reputation: 99508
A function that decides if a list begins with the letter ’a’ can be defined as follows:
test :: [Char] -> Bool
test ['a',_] = True
test _ = False
or
test :: [Char] -> Bool
test ('a':_) = True
test _ = False
Why does the first use []
, while the second uses ()
?
Does the second use ('a':_)
to represent a tuple or a list?
test
's argument have a list type [Char]
?()
represent a tuple and how can it represent a list?Upvotes: 4
Views: 143
Reputation: 16214
In Haskell there are data constructors that are symbols, some examples that may confuse you:
() :: ()
that's the type unit
with its constructor ()
and its value ()
then there is:
(,) :: a -> b -> (a,b)
(,)
is the constructor for tuples, for example (1,"b")
that can be (1,) “b”
or (,) 1 “b”
finally your case:
(:) :: a -> [a] -> [a]
for example, 1:[]
that can be [1]
or (:) 1 []
Upvotes: 1
Reputation: 477240
Does the second use
('a':_)
to represent a tuple or a list?
A list.
If a list, doesn't
()
represent a tuple and how can it represent a list?
No, this is the unit type [wiki]. It is not a tuple, nor a list. Sometimes, as the Wikipedia article says, it is interpreted as an 0-tuple. It is defined in GHC.Tuple
as well.
Why does the first use
[]
, while the second uses()
?
The two are not equivalent. The former one matches a list with exactly two elements where the first element is an 'a'
, whereas the latter matches a list with at least one element where the first element is an 'a'
. But the latter can match a list with one element, three elements, etc. whereas the former can only match lists with exactly two elements.
(:)
is a data constructor of a list. Indeed:
Prelude> :i (:)
data [] a = ... | a : [a] -- Defined in ‘GHC.Types’
infixr 5 :
The ('a': _)
is just a nicer form of ((:) 'a' _)
. We here thus use one of the list data constructors.
The ['a', _]
is syntactical sugar for (:) 'a' ((:) _ [])
, so here we match a list that starts with an 'a'
and where the tail is a list with as head a value we do not care about and its tail the empty list data constructor.
Upvotes: 8
Reputation: 18249
Haskell's list notation is just syntactic sugar for "cons"ing elements on to the empty list (that is, using the :
operator).
In other words,
[x,y,z]
is syntactic sugar for
x:(y:(z:[]))
(although this form would more normally be written as x:y:z:[]
without the parentheses, since :
is right-associative).
So, in the example you quote, ('a':_)
represents any list whose first element is 'a'
, while ['a',_]
is sugar for (a:(_:[]))
which is a list of length exactly 2, whose first element is a
.
Note that tuples are something else entirely, being denoted by a sequence of values in parentheses separated by commas.
Upvotes: 5