This expression appears to be invalid because the first two elements are lists while the last element is a list of list.
[1,2,3]:[4,5]:[[]]
But in fact, it does evaluate and is equal to:
[[1,2,3],[4,5],[]]
How come?
Consider: the following appears to be invalid because the first three elements are ints, while the last is a list:
1 : 2 : 3 : []
But in fact, it does evaluate!
[1, 2, 3]
Or, more directly, and with the same result:
1 : 2 : [3]
[1,2,3]:[4,5]:[[]] is just [1,2,3] : [4,5] : [] : []
If you try
:t [[]]
in GHCI
it give
[[a]]
And [1,2,3], [4,5] is [Int],
and so Haskell infer the type of [[a]] is [[Int]]
therefore, [Int]:[Int]:[[Int]] = [[Int]]
corresponding, [1,2,3]:[4,5]:[[]] = [[1,2,3],[4,5],[]]
This is because : does not separate elements, it is the constructor to prepend an item onto a list (known as cons in lisp tradition).
Prelude> :i (:)
data [] a = ... | a : [a] -- Defined in ‘GHC.Types’
infixr 5 :
Prelude> :t (:)
(:) :: a -> [a] -> [a]
So the value on the right is already the list type that : returns. In this case, those are both [[Int]], and there just happens to be an empty list as the last element in the outer list. Because : is right associative, [1,2,3]:[4,5]:[[]] is equivalent with [1,2,3]:([4,5]:[[]]) or [[1,2,3], [4,5], []].
The prelude list type has two constructors, [] (empty list) and : (the prepend constructor). The [a,b,c] form is syntactic sugar, as specified in the Translation box in Haskell 2010 Languare Report sections 3.7, Lists.
[e1, …, ek] = e1 : (e2 : ( … (ek : [])))
Related
I got a Haskell function that is defined using pattern matching but i'm not really understand why is it looks like the way it is.
safeTail (x : xs) = xs
I'm not really understand specifically at the (x : xs), what does it mean ?
Consider a similar definition for a list data type.
data List a = Empty | Cons a (List a) -- (1)
There are two constructors: one to create an empty list, and another to create a list given a value and another list.
Pattern matching works by matching a value against the constructor used to create it.
safeTail (Cons x xs) = xs -- (2)
That is, if safeTail is applied to a value defined using the Cons constructor, then the return value is the second argument to Cons.
In real code, both the type constructor List and the Empty data constructor are named [] and the Cons constructor is named (:).
data [] a = [] | (:) a ([] a)
which Haskell allows to be written with special syntax
data [a] = [] | a : [a]
Applying the type constructer [] to a type or type variable can be replaced by including the argument inside the [], and the symbolic constructor (because it starts with a :) can be used as an infix operator.
That is, you could write
safeTail ((:) x xs) = xs -- (3)
or
safeTail (x : xs) = xs -- (4)
with (2), (3), and (4) being equivalent to (1) above.
>>> safeTail ((:) 3 ((:) 2 ((:) 1 [])))
[2,1]
>>> safeTail (3:2:1:[])
[2,1]
>>> safeTail [3,2,1]
[2,1]
For further simplicity, Haskell represents (x:[]) as [x], (x:y:[]) as [x,y], etc.
A complete definition of safeTail would also provide a value for an empty list argument:
safeTail [] = []
or a Maybe-based definition
safeTail :: [a] -> Maybe [a]
safeTail [] = Nothing
safeTail (x:xs) = Just xs
Thats the pattern matching.
The first argument to your function safeTail is some list type. In case the argument is a non-empty list, this pattern matching will succeed and bind the x to the head element and xs to the tail of the list.
In case you pass an empty list to safeTail the pattern match will fail and other patterns (if any exists) are checked.
I don't understand the role of the colon in the following lambda expression:
myFunction :: [Int] -> [Int]
myFunction li = foldr (\x acc -> if x < 10 then x : acc else acc) [last li] li
I'm used to seeing the colon for recursive actions, however it looks like this colon is effectively saying prepend to current accumulator list, is that right?
: is a data constructor. It prepends a value of type a to an existing (possibly empty) list of type [a].
let x = 1 : [2,3,4] -- x == [1,2,3,4]
You can picture the list type constructor as being defined like this:
data [] a = [] | a : [] a -- : as an infix operator
data [] a = [] | (:) a ([] a) -- : in prefix positino
which might read more easily as
-- [] == List
-- (:) == Cons
data List a = EmptyList | Cons a (List a)
By "recursive action", I assume you mean you see it being used in a pattern matching situation like
head (a:as) = a
This is not unique to (:); pattern matching can be done with any data constructor.
with
data ListType = List Int Int Int deriving(Show)
[1, 2, 3] and List 1 2 3, can both get a list which contains one to three, can I regard literal as a special form of value constructor?
Not just limits in Haskell.
can I regard literal as a special form of value constructor?
Basically, yes. Do note, however, that your ListType is not a list; it is (equivalent to) a tuple. Values of a list type may hold any number of elements, while ListType values can hold only three. Back to your question, though: [1, 2, 3] is indeed syntax sugar for 1 : 2 : 3 : [], in which the (:) and [] constructors appear explicitly. Weren't it for the sugar and other syntactical details, a definition for the list type might be:
data [] a = [] | (:) a ([] a)
I don't know what you mean by "literal", but the List data type that you defined above is actually not a conventional Haskell list. For one, your "List" has a fixed number of elements (3), while a Haskell list can contain from zero to an infinite number of elements. Your type is also specialized to the type Int, while Haskell lists can contain any type of elements, as long as all elements are of the same type. And, besides, Haskell lists are instances of a number of typeclasses (Functors, Monoids, Monads, etc.).
Haskell lists are a recursive data type and a possible constructor for them would be:
data List a = Empty | Cons a (List a) deriving Show
You could use this constructor as:
Cons 1 (Cons 2 (Cons 3 Empty))
Of course, it would be far more practical to use the built-in data type and build your list as:
[1,2,3]
Also, what do you really mean by "limits in Haskell"?
Haskell allows a custom syntax for lists, such as
[1,2,3]
this is just a syntactic shortcut for
1 : 2 : 3 : []
which is another syntactic shortcut for
(:) 1 ((:) 2 ((:) 3 []))
Above, (:) and [] are data constructors.
(:) :: a -> [a] -> [a]
[] :: [a]
Keep in mind that the special syntax applies only to standard lists, not to user defined types. You can get something vaguely similar with e.g.
data MyList a = Nil | a :+ MyList a
and then using the :+ value constructor in an infix way:
1 :+ 2 :+ 3 :+ Nil
Still, no [1,2,3] syntax for this type.
I'm very new to Haskell, and I decided to learn it some days ago, thanks to the haskell wikibook.
I'm reading at this moment the matching pattern for lists, but I can't understand the syntax for list.
Here's an example (from the wikibook) :
doubleList :: [Integer] -> [Integer]
doubleList [] = []
doubleList (n:ns) = (2 * n) : doubleList ns
I don't understand the part (n:ns). How should I read it ?
You can read it like this: (head:tail), so if you have [1, 2, 3] and you match it with (x:xs), then x will be bound to the first element in the list, 1, and xs will be bound to the rest of the list, in this case [2, 3].
(:) is an operator with type a->[a]->[a]. This means that it takes an item, and a list of those items, and returns another list of the same items. The output list is formed by prepending the input item to the input list.
Here is how you can use it
1:[2,3]
will return
[1,2,3]
Because the (:) appears on the left hand side of the definition, in your case, you are pattern matching, and the operator is being used to deconstruct the value, rather than build it.
For example, if we have
func (first:rest) = ....
and call it like this
func [1,2,3]
the following values would be assigned
first=1 --notice, this is type a
rest=[2,3] --notice, this is type [a]
Another tip that might help you understand is by looking at the definition of the list data type:
data [] a = [] | a : ([] a)
Note that Haskell makes special syntax rules just for the list type, normally [] is not a valid constructor. This definition is equivalent to
data List a = Empty | Cons a (List a)
Where
[] = Empty
(:) = Cons
You would pattern match on this as
doubleList :: List Int -> List Int
doubleList Empty = Empty
doubleList (Cons n ns) = Cons (2 * n) (doubleList ns)
If written using infix form:
doubleList (n `Cons` ns) = (2 * n) `Cons` doubleList ns
So now hopefully you can see the parallels between the two definitions. Haskell also provides the special syntax rule that
[1, 2, 3, 4] = 1:2:3:4:[]
Since the former is much easier to write and read. In fact, whenever you have a list literal like [1, 2, 3, 4] in your code, the compiler first converts it to 1:2:3:4:[] before converting your code into an executable.
I'm reading A Gentle Introduction to Haskell (which is not so gentle) and it repeatedly uses the : operator without directly explaining what it does.
So, what exactly does it do?
: is the “prepend” operator:
x : xs
Returns a list which has x as first element, followed by all elements in xs. In other functional languages, this is usually called cons, because it “cons”tructs a list recursively by repeated application from an empty list:
1 : 2 : 3 : 4 : []
is the list [1, 2, 3, 4].
Could always check out the types in GHCi/HUGS, as the first steps in the tutorial encourage you to download GHC/HUGS.
Prelude> :t (:)
(:) :: a -> [a] -> [a]
Prelude> :t (++)
(++) :: [a] -> [a] -> [a]
From their respective types, it's quite easy to deduce their usage.
PS: http://haskell.org/hoogle/ is awesome.
The : operator in Haskell is the constructor for lists. It 'cons' whatever is before the colon onto the list specified after it.
For instance, a list of integers is made by 'consing' each number onto the empty list, e.g;
The list [1,2,3,4]
can be constructed as follows:
4 : [] (consing 4 to the empty list)
3 : [4] (consing 3 onto the list containing 4)
2 : [3,4] (consing 2 onto the list containing 3, 4)
1 : [2,3,4] (consing 1 onto the list containing 2,3,4)
giving you;
[1,2,3,4]
Written fully that's;
1 : 2 : 3 : 4 : []
It is the type constructor for lists. It is no different from any other type constructor like Just or Left, except that it is infix. Valid type constructors can either be words starting with a capital letter, or symbols starting with a colon.
So you can define infix constructors for your own data types. For example:
data MyList a = a :> MyList a
| Empty
in the above code we define a type called MyList with two constructors: the first is a weird-looking constructor :> which takes an element and another MyList a; the second is an empty constructor Empty which is equivalent to [] in Haskell's native lists.
The above is equivalent to :
data MyList a = Cons a (MyList a)
| Empty