Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does cons work in Haskell :

Tags:

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!

like image 697
Tim H UK Avatar asked Aug 19 '13 11:08

Tim H UK


People also ask

What does Cons do in Haskell?

Anyway, Cons is just the constructor name -- it is an arbitrary name. You can use data List a = Foobar a (List a) .... and name it Foobar , if you wish. Cons is a historic name, though, originating from Lisp. :-: is another arbitrary name for the constructor, except that it can be used infix.

What do Cons operators do?

In Scala, List has an operator :: , which is known as the Cons operator. It is useful to add new elements at the beginning of the List . Here, Cons is short for construct the new List object. We cannot use the Cons operator to add a new element at the end of the List .

What does Colon do in Haskell?

In Haskell, the colon operator is used to create lists (we'll talk more about this soon). This right-hand side says that the value of makeList is the element 1 stuck on to the beginning of the value of makeList .

What does the operator do in Haskell?

Haskell provides special syntax to support infix notation. An operator is a function that can be applied using infix syntax (Section 3.4), or partially applied using a section (Section 3.5).


2 Answers

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"
like image 172
kqr Avatar answered Oct 16 '22 11:10

kqr


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"
like image 28
mhwombat Avatar answered Oct 16 '22 11:10

mhwombat