Tim H UK
Tim H UK

Reputation: 285

How does cons work in Haskell :

Cons doesn't seem to work as I would expect in the second example. What am I missing?

Here cons adds an element to a list, which is great.

1:[2,3]

But with this one it seems to put the first element into list x and the tail into list xs:

let { myInt :: [Int] -> [Int] ; myInt (x:xs) = xs }

I don't really see why this would happen, is it something to do with recursion?

Thanks in advance!

Upvotes: 8

Views: 3644

Answers (2)

kqr
kqr

Reputation: 15028

The : operator can be used to both construct a list and deconstruct a list, depending on where you use it. If you use it in an expression, it is used for constructing a list, just like you said. When you use it in a pattern, it does the reverse – it deconstructs (takes apart) a list.

Constructing a list:

λ> 1:2:[3, 4]
[1,2,3,4]

Deconstructing a list:

λ> let first:second:rest = [1, 2, 3, 4]
λ> first
1
λ> second
2
λ> rest
[3, 4]

The same applies for many data constructors in Haskell. You can use Just to construct a Maybe value.

λ> let name = Just "John"
λ> :type name
name :: Maybe [Char]

However, you could also use it to take apart a Maybe value.

λ> let Just x = name
λ> x
"John"

Upvotes: 11

mhwombat
mhwombat

Reputation: 8126

There are two different things happening here. Your first example uses the (:) operator to create a new list from the element 1 and the list [2,3].

1:[2,3]

Your second example uses pattern matching. The expression...

myInt (x:xs) = ...

...essentially says "if the argument of myInt consists of an element prepended to a (possibly empty) list, then let's call the first element x and the list xs." This example may make it clearer:

λ> let { myInt :: [Int] -> String ; myInt (x:xs) = "The first element is " ++ show x ++ " and the rest of the list is " ++ show xs}
λ> myInt [1,2,3]
"The first element is 1 and the rest of the list is [2,3]"

Note that this will only work if the input list contains at least one element.

λ> myInt []
"*** Exception: <interactive>:9:34-127: Non-exhaustive patterns in function myInt

However, we can handle the case where the input list is empty like this:

λ> let { myInt :: [Int] -> String ; myInt (x:xs) = "The first element is " ++ show x ++ " and the rest of the list is " ++ show xs; myInt _ = "empty list"}
λ> myInt []
"empty list"

Upvotes: 9

Related Questions