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!
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.
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 .
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 .
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).
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"
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"
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With