when you split a list using x:xs syntax why is it wrapped in a parentheses? what is the significance of the parentheses? why not [x:xs] or just x:xs?
The cons cell doesn't have to be parenthesized in every context, but in most contexts it is because
Function application binds tighter than any infix operator.
Burn this into your brain in letters of fire.
Example:
length [] = 0
length (x:xs) = 1 + length xs
If parentheses were omitted the compiler would think you had an argument x followed by an ill-placed infix operator, and it would complain bitterly. On the other hand this is OK
length l = case l of [] -> 0
x:xs -> 1 + length xs
In this case neither x nor xs can possibly be construed as part of a function application so no parentheses are needed.
Note that the same wonderful rule function application binds tighter than any infix operator is what allows us to write length xs in 1 + length xs without any parentheses. The infix rule giveth and the infix rule taketh away.
You're simply using the cons operator :, which has low precedence. Parentheses are needed so that things stay right.
And you don't use [x:xs], because that would match a list whose only element is a list with head x and tail xs.
I don't know exact answer, but I guess that is due to what can be matched in patterns. Only constructors can be matched. Constructors can be of single word or composite. Look at the next code:
data Foo = Bar | Baz Int
f :: Foo -> Int
f Bar = 1
f (Baz x) = x - 1
Single word constructors match as is. But composite constructors must be surrounded with parens in order to avoid ambiguity. If we skip parens it looks like matching against two independent arguments:
f Baz x = x - 1
So, as (:) is composite it must be in parens. Skipping parens for Bar is a kind of syntactic sugar.
UPDATE: I realized that (as sykora noted) it is a consequence of operator precedence. It clarifies my assumptions. Function application (which is just space between function and argument) has highest precedence. Others including (:) have lower precedence. So f x:xs is to be interpreted as ((:) (f x)) xs that is presumably not what we need. While f (x:xs) is interpreted as f applied to x:xs which is in turn (:) applied to x and xs.
It's to do with parsing.
Remember, the colon : is just a constructor that's written with operator syntax. So a function like
foo [] = 0
foo (x:xs) = x + foo xs
could also be written as
foo [] = 0
foo ((:) x xs) = x + foo xs
If you drop the parenthesis in that last line, it becomes very hard to parse!
: is a data constructor, like any other pattern match, but written infix. The parentheses are purely there because of infix precedence; they're actually not required and can be safely omitted when precedence rules allow. For instance:
> let (_, a:_) = (1, [2, 3, 4]) in a
2
> let a:_ = "xyzzy"
'x'
> case [1, 2, 3] of; a:b -> a; otherwise -> 0;
1
Interestingly, that doesn't seem to work in the head of a lambda. Not sure why.
As always, the "juxtaposition" operator binds tighter than anything else, so more often than not the delimiters are necessary, but they're not actually part of the pattern match--otherwise you wouldn't be able to use patterns like (x:y:zs) instead of (x:(y:zs)).
Related
As the title implies, I am unsure about the difference between square brackets and parentheses in regard to lists.
Two versions of Haskell's insert defined, one using square brackets, the other using parentheses:
insert' :: Int -> [Int] -> [Int]
insert' y [] = [y]
insert' y (x:xs) | y <= x = y:x:xs | otherwise = x : insert' y xs
----
insert' y [x:xs] | y <= x = y:x:xs | otherwise = x : insert' y xs
What is the reason the second definition of insert' doesn't work?
The error message it gives, for anyone wondering:
test.hs:3:12: error:
• Couldn't match expected type ‘Int’ with actual type ‘[Int]’
• In the pattern: x : xs
In the pattern: [x : xs]
In an equation for ‘insert'’:
insert' y [x : xs]
| y <= x = y : x : xs
| otherwise = x : insert' y xs
|
3 | insert' y [x:xs] | y <= x = y:x:xs | otherwise = x : insert' y xs
|
As in almost all other languages, parentheses in Haskell don't really do anything. They help the parser know which things you intended to group together, and that's it; they don't change the meaning of the thing that's inside them, and if the parser could magically guess which way you intended to group things at every choice point we wouldn't need them at all. So all of these patterns behave exactly the same:
x
(x)
((x))
(((((((((x)))))))))
All of these patterns are also exactly the same:
x:xs
(x:xs)
((x:xs))
(((((((((x:xs)))))))))
Sometimes we must use one of the later ones -- like (x:xs) -- instead of the first one -- x:xs -- to inform the parser that we intended these things to be grouped together. But the parentheses don't otherwise change anything about what the pattern means.
Square brackets, on the other hand, are used for constructing lists. They have an actual run-time meaning: they allocate a new data structure in memory and initialize it. For example, 3 is a number, but [3] is a list with a single element, [3,4] is a list with two elements, [[3]] is a list of lists, and so on. The same behavior applies to patterns:
x -- match anything (even a list!) and bind x to its value
[x] -- match a list with a single element, and bind x to that element's value
[x,y] -- match a list with two elements, and bind x and y to those elements' values
[[x]] -- match a nested list; the outer and inner lists both have one element; bind x to the first element's first element
Now we can address your specific example. The pattern x:xs is a pattern that matches any list with at least one element, binding x to that first element and xs to the rest of the list. The pattern (x:xs) does exactly the same thing. The pattern [x:xs], on the other hand, matches a list with exactly one element, because there are square brackets; the only element of that list is then matched against the pattern x:xs, with the behavior described above.
One consequence of this is that x:xs can match lists with any type of element -- say, Int -- but [x:xs] can only match lists whose elements are lists.
(x:xs) as a pattern will match any non-empty list with x its head and xs its tail.
[x:xs] as a pattern will match a singleton list -- a list containing exactly one item -- which is a non-empty list, matching the pattern (x:xs). The pattern [x:xs] is in fact equivalent to the pattern [(x:xs)]. It is a nested pattern, and Haskell allows that. The outer pattern matches a singleton list, and the inner pattern matches a non-empty list. The parentheses in this position are optional.
That's why your second definition implies the type of the second argument is [[a]], but you've declared it to be [Int]. And Int can't match [a]. (That a is also determined to be an Int, since you compare x and y, and y the first argument is declared to be an Int, but that doesn't change anything).
[ [a] ]
[ Int ]
----------------
***mismatch***
Doing the third of the 99-Haskell problems (I am currently trying to learn the language) I tried to incorporate pattern matching as well as recursion into my function which now looks like this:
myElementAt :: [a] -> Int -> a
myElementAt (x ++ xs) i =
if length (x ++ xs) == i && length xs == 1 then xs!!0
else myElementAt x i
Which gives me Parse error in pattern: x ++ xs. The questions:
Why does this give me a parse error? Is it because Haskell is no idea where to cut my list (Which is my best guess)?
How could I reframe my function so that it works? The algorithmic idea is to check wether the list has the length as the specified inde; if yes return the last elemen; if not cut away one element at the end of the list and then do the recursion.
Note: I know that this is a really bad algorithm, but it I've set myself the challenge to write that function including recursion and pattern matching. I also tried not to use the !! operator, but that is fine for me since the only thing it really does (or should do if it compiled) is to convert a one-element list into that element.
Haskell has two different kinds of value-level entities: variables (this also includes functions, infix operators like ++ etc.) and constructors. Both can be used in expressions, but only constructors can also be used in patterns.
In either case, it's easy to tell whether you're dealing with a variable or constructor: a constructor always starts with an uppercase letter (e.g. Nothing, True or StateT) or, if it's an infix, with a colon (:, :+). Everything else is a variable. Fundamentally, the difference is that a constructor is always a unique, immediately matcheable value from a predefined collection (namely, the alternatives of a data definition), whereas a variable can just have any value, and often it's in principle not possible to uniquely distinguish different variables, in particular if they have a function type.
Yours is actually a good example for this: for the pattern match x ++ xs to make sense, there would have to be one unique way in which the input list could be written in the form x ++ xs. Well, but for, say [0,1,2,3], there are multiple different ways in which this can be done:
[] ++[0,1,2,3]
[0] ++ [1,2,3]
[0,1] ++ [2,3]
[0,1,2] ++ [3]
[0,1,2,3]++ []
Which one should the runtime choose?
Presumably, you're trying to match the head and tail part of a list. Let's step through it:
myElementAt (x:_) 0 = x
This means that if the head is x, the tail is something, and the index is 0, return the head. Note that your x ++ x is a concatenation of two lists, not the head and tail parts.
Then you can have
myElementAt(_:tl) i = myElementAt tl (i - 1)
which means that if the previous pattern was not matched, ignore the head, and take the i - 1 element of the tail.
In patterns, you can only use constructors like : and []. The append operator (++) is a non-constructor function.
So, try something like:
myElementAt :: [a] -> Int -> a
myElementAt (x:xs) i = ...
There are more issues in your code, but at least this fixes your first problem.
in standard Haskell pattern matches like this :
f :: Int -> Int
f (g n 1) = n
g :: Int -> Int -> Int
g a b = a+b
Are illegal because function calls aren't allowed in patterns, your case is just a special case as the operator ++ is just a function.
To pattern match on lists you can do it like this:
myElementAt :: [a] -> Int -> a
myElementAt (x:xs) i = // result
But in this case x is of type a not [a] , it is the head of the list and xs is its tail, you'll need to change your function implementation to accommodate this fact, also this function will fail with the empty list []. However that's the idiomatic haskell way to pattern match aginst lists.
I should mention that when I said "illegal" I meant in standard Haskell, there are GHC extensions that give something similar to that , it's called ViewPatterns But I don't think you need it especially that you're still learning.
So I was reading through a Haskell guide online, and was just curious about the combination of infix operators and filter.
Say you have a function like
filter (>5) [6, 10, 5]
That will return [6,10], which seems like the intuitive way filter should work.
However, doing
filter ((>) 5) [6, 10, 5]
returns an empty list (this still makes sense, (>) checks if its first argument is larger than the second argument).
However, filter is typically defined something like
filter :: (a -> Bool) -> [a] -> [a]
filter _ [] = []
filter p (x:xs)
| p x = x : filter p xs
| otherwise = filter p xs
When the type system knows it has an infix operator, are most of those infix operators written so that a partially applied function needs a leading argument to the original prefix function? i.e. is infix > defined as something like (butchered syntax)
infix> :: Int -> Int-> Bool
infix> x y = (>) y x
x infix> y = (>) x y
Sorry if this question doesn't make sense, I feel like I'm missing something basic in how p x is evaluated when p is a partially applied infix operator.
(>5) and ((>) 5) are two different types of expression.
The first is what is known as a section. Sections are of the form (op exp) or (exp op) where op is an infix operator and exp is another expression. A section takes an argument and applies it on the missing side, so (>5) 4 = (4 > 5) and (5>) 4 = (5 > 4). In other words, (>5) is equivalent to \x -> x > 5.
In ((>) 5), (>) is the infix operator > converted to an expression. ((>) 5) then is the application of 5 to the function (>), which gives a new function that takes the next argument. If we apply that argument, e.g., (>) 5 4, we get the prefix equivalent of (5 > 4).
This conversion of an infix operator to an expression that can be used prefix works for all infix operators. You can also go the other way and covert an identifier into an infix operator, i.e.:
`foo`
You can even say:
(`foo`)
to turn it back into an expression.
While trying to write a function for transposing a list of lists, I saw something very curious. I tried:
> let abc xs | null (head xs) = [] | otherwise = map head xs : abc $ map tail xs
and got an error. Then I tried:
> let abc xs | null (head xs) = [] | otherwise = map head xs : abc ( map tail xs )
> abc [[1,2,3], [4,5,6], [7,8,9]]
[[1,4,7],[2,5,8],[3,6,9]]
I was led to believe that the $ operator can be used instead of the brackets, and that that's more Haskellish. Why am I getting an error?
An operator is a function that can be applied in a infix position. So $ is a function.
In Haskell, you can define your own functions that can be used in infix position - between the arguments. Then you can also define function application precedence and associativity using infix, infixr, infixl - that is, the clues telling the compiler whether to treat a $ b $ c as (a $ b) $ c, or a $ (b $ c).
The precedence of $ is such that your first expression is interpreted like (map head xs : abc) $ ...
For example, to declare $ as infix, place its name in ():
($) :: (a->b) -> a -> b
f $ x = f x
or composition:
(.) :: (b->c)->(a->b)->a->c
(f . g) x = f $ g x
Arithemtic "operators" are also defined as infix functions in class Num.
Additionally, you can use other functions as infix, by quoting them in backticks `` at the application site. Sometimes it makes the expression look prettier:
f `map` xs == map f xs
(not that in this particular case it makes it look pretty, just to show a simple example)
Adding to Sassa's correct answer, let's dissect the code snippet you provided a bit further:
map head xs : abc $ map tail xs
Two operators are used here: (:) and ($). As noted above, these are interpreted as infix by default because their names consist only of symbols.
Each operator has a precedence which decides how 'tightly' it binds or, perhaps more usefully, which operator is applied first. Your code could be interpreted either as
((map head xs) : abc) $ (map tail xs)
where (:) binds more tightly (is applied before) ($) or as
(map head xs) : (abc $ (map tail xs))
where ($) binds more tightly. Note that I have put parentheses around function application (for example map applied to tail and xs) as well. Function application binds more tightly than any operator and is thus always applied first.
To decide which of the two ways to interpret the code is correct, the compiler needs to get information about which operator should bind more tightly. This is done using a fixity declaration like
infix 8
or in general
infix i
where i is between 0 and 9. Higher values of i mean that an operator binds more tightly. (infixr and infixl may be used to additionally define associativity as explained in Sassa's answer, but this doesn't affect your specific problem.)
As it turns out, the fixity declaration for the ($) operator is
infixr 0 $
as seen in the Prelude documentation. (:) is a bit more 'magic' because it is hard-coded into the Haskell syntax, but the Haskell Report specifies that it has precedence 5.
Now we finally have enough information to conclude that the first interpretation of your code is indeed correct: the precedence of (:), 5, is higher than the precedence of ($), 0. As a general rule of thumb, ($) often doesn't interact well with other operators.
By the way, if an expression contains two different operators which have the same precedence (such as (==) and (/=)), the order in which they should be applied is unclear, so you have to use parentheses to specify it explicitly.
This question already has answers here:
What does the : infix operator do in Haskell?
(4 answers)
Closed 8 years ago.
I've tried looking it up in hoogle and other various haskell dictionaries, but I can't find it. I was under the impression that it prepends, but I'm starting to see it in ways I haven't before and I've started second guessing myself.
For example, this is one of the questions that I don't understand:
(3 points) Fill in the blank with a pattern such that fun1 [(5,6),(7,8)] returns
5 and fun1 [(10,20),(30,40),(50,60)] returns 10:
and the answer is apparently:
((y,_):_)
fun1 _____________ = y
But I am so confused by this. I understand that the underscores mean that you don't really care about what the types of those are, but I don't understand what the (:) does in this answer.
While the other answers correctly explain what : is they don't quite answer the question - in the answer you have in your question : isn't used as a function, but as a constructor to pattern match on. fun (x:xs) = x means "if the argument is of the format (x:xs) give me the x". Pattern matching is used to "pull apart" complex types based on their constructors in Haskell.
In particular, since : is a list constructor you can pull apart lists with :
(conceptually list is defined as data [] a = [] | (:) a [a], although you're not gonna get this to compile because it's builtin syntax).
A non list example: We could define a datatype data F a b = A a | B b. This would create a type F that's parameterized with two types a and b and two constructors A and B with the types a -> F a b and b -> F a b respectively.
You could then write functions that use pattern matching to get at the contained values, like
isA (A _) = True -- this value was constructed with A, so it is an A
isA (B _) = False -- this value was constructed with B so it is not an A
or
getA (A a) = a -- this value was constructed with A so we can get an a out of it
getA (B _) = undefined -- ohps! We can't get an a back here cause we don't have one!
It is a List constructor function. It is used for prepending any value in front of the list.
ghci> 2 : [3,4]
[2,3,4]
It is just another Haskell function. You can also see it's type in ghci:
ghci> :t (:)
(:) :: a -> [a] -> [a]
Regarding your question, the answer is like this ((y,_):_) because it is being used in pattern matching. The first _ is the second element of the pair and the second _ pattern matches a list.
This may help you:
ghci> (5,6):[(7,8)]
[(5,6),(7,8)]
: is the list constructor of type a -> [a] -> [a]. It is usually used infix. but you can use it as prefix if you surround it with parentheses as you did. Just like any infix operation. (E.g. (+) 4 5 == 4 + 5)
So (:) a as is the same as a:as
Every constructor in Haskell can be also used do deconstruct a value of the type if constructs in a pattern match:
f x:xs = xs
would for example define a function that takes a non empty list and returns the tail. It would fail on an empty list because the empty list is constructed by the nullary constructor []. You could make f total by adding that second constructor to the match.
f [] = []
I guess your confusion comes from the fact that in haskell there is syntactic sugar that allows you to write lists in a more convenient way. Instead of (1:(2:(3:[]))) you can write [1,2,3] which is expanded into the former by the compiler.
In addition to the answers of what (:) function does, please, bear in mind that in the context of your question : is used as a deconstructor.
It is better to view (:) as a constructor. Then, just like any other data constructor, it can be used to introspect the contents of the value. Examples are:
f (Just x) = x -- extracts the value wrapped into Maybe a
f (x:_) = x -- extracts the value wrapped into a list, [a]
f ((x,_):_) = x -- extracts the value wrapped into a tuple in the list of tuples
In all these cases Just, : and (,) are constructors. The same syntax can be used to construct or deconstruct the values - depending on the context of the expression. Compare:
f x = Just x -- wraps x into Maybe a
f x xs = x:xs -- wraps x into a list, [a]
f x y z = (x,y):z -- wraps x into a tuple in the list of tuples
To understand what fun1 does, let's first look at another function:
f (x:xs) = x
If you pass this function a list such as [5,12,33], it will match x to 5, and xs to [12,33]. The function just returns x, i.e. the first element. So this function is basically the same as head. Since we don't actually use the value xs, we can rewrite the function as:
f (x:_) = x
Now let's look at fun1, but a slightly modified version.
fun1 ((y,z):xs) = y
If we pass this function the list [(5,6),(7,8)], it will match (y,z) to the pair (5,6) and xs to [(7,8)]. So now y is 5, and that's the value we return. Again, since we don't use z or xs, we can write the function as:
fun1 ((y,_):_) = y