Do we have to use parentheses in pattern matching in function declarations ?
In example below, I have a pattern x:xs where x takes first element from the list and xs contains the rest.
I would like to ask whether parentheses are a necessary part of this pattern matching.
head' :: [a] -> a
head' [] = error "Can't call head on an empty list!"
head' (x:_) = x
I tried to use it without braces but it causes error during loading into ghci.
Parentheses are not part of pattern matching, in the same sense that they are not part of expression evaluation. That being said, parentheses are certainly part of pattern and expression syntax.
Look, if you write
h x:xs
this looks like
(h x) : xs
to the parser. Hence we write
h (x:xs)
both on the left hand side and on the right hand side of the equal sign. As expression, it means "function h applied to a list constructed of x and xs", and on the left hand side it defines an equation for that application.
Related
In Haskell, I know that there are tuples (x1,x2,x3) and also lists [x1,x2,x3] and that tuples are not homogeneous and have a fixed length.
On the other hand, lists can be rewritten for example in the form x1:x2:x3:[], which I guess is a function a ->[a]->[a], which makes some sense to me, but in the following code:
head' :: [a] -> a
head' [] = error
head' (x:_) = x
it is unclear to me why we use parentheses, which is to my understanding tuple notation. It looks more like we should have something like an uncurry function on the colon operator, and take the first input, or something like that.
How are the parentheses behaving here, and why can we not use brackets in some way or another?
Parentheses denote tuples when they contain commas. Parentheses without commas are used for grouping, e.g. to distinguish between x - (y - z) and (x - y) - z or, in this case, between head' (x:_) = x and (head' x) : _ = x. In other words, all that the parentheses do here is to denote that : is being applied to x and _ rather than head' x and _.
If you used [] here, that would be a list pattern. Generally the pattern [p] matches if the given value is a list with one element and that element matches the pattern p. So [x:_] matches a list that contains one element and that element is itself a list matching the pattern x:_. Since that's not what you want, you need to use the version without the list pattern.
The parentheses in head' (x:_) are just being used for grouping; you can tell no tuples are involved because there are no commas inside. Without the parentheses, head' x:_ would be parsed as (head' x):_, which doesn't work on the left-hand side of an assignment.
We can't use brackets here because they would require knowing how many elements are in the list passed to head'.
I'm just wondering, for recursion example:
squaresRec :: [Double] -> [Double]
squaresRec [] = []
squaresRec (x:xs) = x*x : squaresRec xs
Why on the recursive case, there is no bracket? Shouldn't it suppose to be like this:
squaresRec :: [Double] -> [Double]
squaresRec [] = []
squaresRec [x:xs] = x*x : squaresRec xs
I know this will not work. But just wondering the explanation behind it.
[] matches the empty list.
[1] matches a list containing exactly one element, and that must be a number equal to one. Note that [1] is actually syntactic sugar for (1:[]), i.e. what this really matches is: a list beginning with the number 1, followed by a list that is empty... which is just a complicated way of saying “a list containing the single element 1”.
(x:xs) matches a list that begins with x, followed by xs (and that may contain any number of elements, possibly zero). I.e. this pattern matches any list with at least one element.
[x:xs] matches again a list which contains exactly one element, and that element should match the pattern (x:xs). (Which doesn't make sense even type-wise, because your lists contain Double-numbers, not lists.)
I had the same problem because I'm coming from Erlang.
The thing to understand is that the [head|tail] pattern we have in Erlang is actually translated by the cons function in Haskell, which is the : operator. The parenthesis are just here to isolate the function parameters, like (3+4) would do.
I know it's tempting to ask "why though???" and that it visually makes more sense, but : is how we build (and separate when pattern-matching) the head and the tail of a linked list.
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.
I am trying to implement Standard words function of Haskell. I am using State Monad to solve the problem.
My Code is :
type WorS = ([String],String,String)
words' :: State WorS [String]
words' = do
(lwords, words, x:xs) <- get
case x:xs of
(' ':xs) -> (put (words:lwords, [], xs) >> words')
([]) -> return lwords
(_:xs)-> (put (lwords, words ++ [x], xs) >> words')
run_word' :: String ->[String]
run_word' x = reverse $ fst (runState words' ([], [], x))
When I do:
run_word' "guns and roses"
I get this error:
Exception: Pattern match failure in do expression
The code is loading in ghci without any error. What am I doing wrong?
(lwords,words,x:xs)<-get
x:xs matches a list with at least one element (x becomes the first element, and xs becomes the rest of the list), so you get a pattern match failure when the third member of the tuple is [].
Solution: replace
(lwords,words,x:xs)<-get
case x:xs of
with
(lwords,words,xs)<-get
case xs of
(And consider using different variable names later in the function: it gets confusing when you have two or more variables with the same name.)
Edit: if you turn on warnings (pass the -Wall flag to ghc/ghci), you will get warned at compile time that the pattern may fail to match at runtime. (You'll also get a warning about having one xs variable hiding another xs variable, called shadowing.)
I'm working through Learn You A Haskell in order to come up to speed with the basics of Haskell. I'm very comfortable with both functional programming and pattern matching, but the latter more so with how Mathematica does it.
In the same spirit as the naïve implementation of head in Chapter 4.1, I proceeded with a naïve implementation of last as:
last1 :: [a] -> a
last1 (_:x:[]) = x
However, calling last1 [1,2,3,4] gave an error Exception: ... Non-exhaustive patterns in function last1. I understand that this error implies that the pattern specified does not cover all possible inputs and usually, a catch-all pattern is necessary (which I've not provided). However, I'm not exactly sure why I get this error for my input.
Question 1: My understanding (of my incorrect approach) is that the first element is captured by _ and the rest get assigned to x, which isn't exactly what I had intended. However, shouldn't this give a type error, because I specified [a] -> a, but x is now a list?
Note that this is not about how to write a working last function — I know I can write it as (among other possibilities)
last2 :: [a] -> a
last2 [x] = x
last2 (_:x) = last2 x
Question 2: Along the same theme of better understanding pattern matching in Haskell, how can I use pattern matching to pick out the last element or more generally, the nth element from a given list, say, [1..10]?
This answer suggests that you can bind the last element using pattern matching with the ViewPatterns extension, but it seems strange that there isn't an analogous "simple" pattern like for head
In Mathematica, I would probably write it as:
Range[10] /. {Repeated[_, {5}], x_, ___} :> x
(* 6 *)
to pick out the 6th element and
Range[10] /. {___, x_} :> x
(* 10 *)
to pick out the last element of a non-empty list.
I apologize if this is covered later in the text, but I'm trying to relate each topic and concept as I come across them, to how it is handled in other languages that I know so that I can appreciate the differences and similarities.
To make sense of the result of your first attempt, you need to see how the
list data is defined. Lists enjoy a somewhat special syntax, but you would
write it something like this.
data List a = (:) a (List a)
| []
So, your list [1 .. 10] is actually structured as
(1 : (2 : (3 : (4 : []))))
In addition, due to the right associativity of the (:) operator, your pattern
for last1 actually looks like
last1 :: [a] -> a
last1 (_:(x:[])) = x
That is why 'x' has same type as an element of your list; it is the first
argument to the (:) constructor.
Pattern matching allows you to deconstruct data structures like lists, but you
need to know what "shape" they have to do so. That is why you cannot directly
specify a pattern that will extract the last element of a list, because there
are an infinite number of lengths a list can have. That is why the working
solution (last2) uses recursion to solve the problem. You know what pattern
a list of length one has and where to find the final element; for everything
else, you can just throw away the first element and extract the last element
of the resulting, shorter, list.
If you wanted, you could add more patterns, but it would not prove that
helpful. You could write it as
last2 :: [a] -> a
last2 (x:[]) = x
last2 (_:x:[]) = x
last2 (_:_:x:[]) = x
...
last2 (x:xs) = last2 xs
But without an infinite number of cases, you could never complete the function
for all lengths of input lists. Its even more dubious when you consider the fact that
lists can actually be infinitely long; what pattern would you use to match that?
There is no way to have pattern match get the "last" element without using view patterns. That is because there is no way to get the last element of a list without using recursion (at least implicitly), and what is more, there is no decidable way to get the last element.
Your code
last1 (_:x:[]) = x
should be parsed like
last1 (_:(x:[])) = x
which can be de-sugared into
last1 a = case a of
(_:b) -> case b of
(x:c) -> case c of
[] -> x
having completed this exercise we see what your code does: you have written a pattern that will match a list IF the outermost constructor of a list is a cons cell AND the next constructor is a cons AND the third constructor is a nil.
so in the case of
last1 [1,2,3,4]
we have
last1 [1,2,3,4]
= last1 (1:(2:(3:(4:[]))))
= case (1:(2:(3:(4:[])))) of
(_:b) -> case b of
(x:c) -> case c of
[] -> x
= case (2:(3:(4:[]))) of
(x:c) -> case c of
[] -> x
= let x = 2 in case (3:(4:[])) of
[] -> x
= pattern match failure
Your example
last1 (_:x:[]) = x
only matches lists containing two elements i.e. lists of the form a:b:[]. _ matches the head of the list without binding, x matches the following element, and the empty list matches itself.
When pattern matching lists, only the right-most item represents a list - the tail of the matched list.
You can get the nth element from a list with a function like:
getNth :: [a] -> Int -> a
getNth [] _ = error "Out of range"
getNth (h:t) 0 = h
getNth (h:t) n = getNth t (n-1)
This built-in using the !! operator e.g. [1..10] !! 5
You can indeed use ViewPatterns to do pattern matching at the end of a list, so let's do:
{-# LANGUAGE ViewPatterns #-}
and redefine your last1 and last2 by reversing the list before we pattern match.
This makes it O(n), but that's unavoidable with a list.
last1 (reverse -> (x:_)) = x
The syntax
mainFunction (viewFunction -> pattern) = resultExpression
is syntactic sugar for
mainFunction x = case viewFunction x of pattern -> resultExpression
so you can see it actually just reverses the list then pattern matches that, but it feels nicer.
viewFunction is just any function you like.
(One of the aims of the extension was to allow people to cleanly and easily use accessor functions
for pattern matching so they didn't have to use the underlying structure of their data type when
defining functions on it.)
This last1 gives an error if the list is empty, just like the original last does.
*Main> last []
*** Exception: Prelude.last: empty list
*Main> last1 []
*** Exception: Patterns.so.lhs:7:6-33: Non-exhaustive patterns in function last1
Well, OK, not exactly, but we can change that by adding
last1 _ = error "last1: empty list"
which gives you
*Main> last1 []
*** Exception: last1: empty list
We can of course use the same trick for last2:
last2 (reverse -> (_:x:_)) = x
last2 _ = error "last2: list must have at least two elements"
But it would be nicer to define
maybeLast2 (reverse -> (_:x:_)) = Just x
maybeLast2 _ = Nothing
You can carry on this way with for example last4:
last4 (reverse -> (_:_:_:x:_)) = x
And you can see that using the reverse viewpattern,
we've changed the semantics of (_:_:_:x:_) from
(ignore1st,ignore2nd,ignore3rd,get4th,ignoreTheRestOfTheList) to
(ignoreLast,ignore2ndLast,ignore3rdLast,get4thLast,ignoreTheRestOfTheList).
You note that in Mathematica, the number of underscores is used to indicate the number of elements being ignored.
In Haskell, we just use the one _, but it can be used for any ignored value, and in the presence of the
asymmetric list constructor :, the semantics depend on which side you're on, so in a:b, the a must mean an
element and the b must be a list (which could itself be c:d because : is right associative - a:b:c means
a:(b:c)). This is why a final underscore in any list pattern reresents ignoreTheRestOfTheList, and in the
presence of the reverse viewfunction, that means ignoring the front elements of the list.
The recursion/backtracking that's hidden under the hood in Mathematica is explicit here with the viewFunction reverse (which is a recursive function).