Reputation: 625
I've been reading through Real World Haskell and I've come across an interesting solution to an exercise in chapter 2.
The exercise asks the reader to construct a function that behaves similarly to Haskell's drop
. One solution looks like this:
lastButOne :: [a] -> a
lastButOne (x:xs) = if length xs == 1
then x
else lastButOne xs
With an improved version looking like this:
lastButOne :: [a] -> a
lastButOne (x1:[x2]) = x1
lastButOne (x:xs) = lastButOne xs
I'm having quite a bit of trouble understanding what the infix colon is doing here. Can somebody give me an idea of how I should be reading this?
From what I understand, elem:[b]
tells Haskell to prepend elem
to [b]
.
But let's suppose I define a function like lastButOne (x:xs)
. Then let's suppose I have a list testCase = [p,q..r]
. Would I be right in presuming that lastButOne
would treat testCase
as two separate objects, i.e. [p]
and [q..r]
?
If that's the case, the reading the first iteration of lastButOne
feels totally intuitive. But then I still don't understand how the second iteration of lastButOne
works.
Upvotes: 2
Views: 1241
Reputation: 827
The :
operator is commonly referred to as cons
(adopted from Lisp parlance). (x:xs)
is a common Haskell pattern match, where (x:xs)
is an [a]
, x
is the head / first element of the list (an a
), and xs
is the tail / rest of the list (an [a]
or list of a
s).
Prelude> let a = (1:2:3:[])
Prelude> let b = (1:[2,3])
Prelude> a
[1,2,3]
Prelude> b
[1,2,3]
Upvotes: 0
Reputation: 625
LIGHTBULB.
lastButOne :: [a] -> a
lastButOne (x1:[x2]) = x1
lastButOne (x:xs) = lastButOne xs
This code works like so: Haskell checks the pattern (x1:[x2])
against the object passed to lastButOne
. (x1:[x2])
is a pattern matching a singleton list prepended by an item of the same type as x2
. A list like this [1,2]
fits this pattern and could be written as 1:[2]
, while a list like this [1,2,3]
does not fit the pattern. Since the first pattern match fails, Haskell falls through to the 'catch-all' pattern, x:xs
.
Upvotes: 0
Reputation: 83567
lastButOne (x:xs)...
has only one parameter, as you can see from the function's type. The (x:xs)
is a pattern which matches a list with at least one element. The first element is named x
and the rest of the list is named xs
.
Upvotes: 4