Is "List" specially handled in Haskell's pattern matching? - haskell

I am a newbie in Haskell and hope this question is not silly.
I have seen so much example that when I am having a list, I am able to match and bind "composition element" of the list to individual variable:
listSizeDesc :: [a] -> String
listSizeDesc [] = "Emtpy"
listSizeDesc (x:xs) = "Something inside"
However, I tried to do something like:
foo :: Int -> String
foo 0 = "Zero"
foo (n - 1) = "next number is " ++ show n
It doesn't work.
It seems to me that both (n-1) and (x:xs) describe how the argument is "created" and bind the "component" to an argument. Is the way List matched specially designed for ease of recursion? Coz it seems to me this matching / argument-binding logic doesn't apply to other functions except (:).

The problem you're encountering is that pattern matching only works with data constructors. A data constructor is in essence very simple; it just takes data values and groups them together in some sort of structure. For example, data Foo = Bar a b simply takes two pieces of data and groups them together under the Foo label. The (:) function you use in your first example is more than just a function; it's a data constructor. It constructs a new list by adding the left argument to the right argument.
Now, pattern matching is merely doing the opposite of this process. It deconstructs a datatype. When you write (x:xs) in your pattern, you're extracting the two pieces of data that the constructor originally stitched together. So all pattern matching does is extract the data that a constructor previously stitched together.
There is one exception: n+k patterns. In Haskell98, you were allowed to use patterns of the form (n+k). This was sort of an arbitrary exception and it was recently removed. If you'd like, you can still use it if you include the NPlusKPatterns language pragma.

The list type is "Sum type" with a constructor, something like:
data List a =
cons a (List a)
| nil
You first example is a pattern match on a datatype (with syntactic sugar for :).
Your second example is a pattern match on integers, which are not a datatypye definition. On integer, there is no pattern using your syntax. You may write your example with:
foo :: Int -> String
foo 0 = "Zero"
foo n = "next number is " ++ show (n+1)
On a side note if you encode integers with datatypes like:
data Nat = Zero | Succ Nat deriving (Show)
Then you can use your pattern match as you wanted initially.
foo :: Nat -> String
foo Zero = "Zero"
foo n#Succ(p) = "next number is " ++ show(n)
Here the pattern Succ(p) plays the role of n-1.

There are already some great answers, so I won't bother with the main question. This is not the best use of it, but what you were trying to do can sort of be accomplished with view patterns.
{-# LANGUAGE ViewPatterns #-}
foo :: Int -> String
foo 0 = "Zero"
foo (pred -> n) = "Next number is " ++ show n

Just to put it as simply as possible:
A list literally is a series of concatenations. A number could be equivalent to the result of an arithmetic operation. The difference is that the result of a : b is simply a : b.
In more detail:
Lists and (:) aren't a special case at all. Let's make our own:
data List2 a = End -- equivalent of "[]"
| Cat a (List2 a) -- non-infix ":"
deriving (Show)
So [1, 2, 3], which == (1 : (2 : (3 : []))), would be written as:
a = Cat 1 (Cat 2 (Cat 3 End))
Just like pattern-matching (x:xs), we can pattern-match List2:
newTail End = End
newTail (Cat _ x) = x
Test it:
*Main> tail [1,2,3]
[2,3]
*Main> newTail a
Cat 2 (Cat 3 End)

moo :: Int -> String
moo 0 = "Zero"
moo n = "next number is " ++ show (n + 1)
n - 1 is an ordinary function application, not a pattern. An exception used to be made for + and this might be the model you are going by. You can write something like
goo :: Int -> String
goo 0 = "Zero"
goo (n+1) = "previous number is " ++ show n
in hugs ; you still can do this with the ghc, if you include the pragma
{-#LANGUAGE NPlusKPatterns#-}

Related

Using lists in Haskell

I'm trying to learn list in Haskell but I have a error that I don't understand
I've been trying to definition arguments, but honestly I don't understand too much of haskell yet.
lefgNLista:: [Int]->[Int]->Int
lefgNLista []=[]
lefgNLista (fre1:fre2) fre3 = if fre1 == fre3 then 1+lefgNLista else fre1 : lefgNLista fre2
Also tried like this but got another error
lefgNLista []=[]=0
I expect the function to count the amount of N numbers in the list, e.g.
ghci> lefgNLista [1,3,5,7,8,8,2,3,8] 8
3
Here is a possible definition explained item by item.
I will omit the type. You can give this function the type of [Int]->[Int]->Int if you want, but it's not the best possible type. The compiler is able to infer the best type for you.
There are two parts in the definition, one for the empty list and one for non-empty lists.
How many elements are in an empty list? Zero. How many of those are equal to any given value? Also zero.
lefgNLista [] _ = 0
-- [] ⇒ the empty list
-- _ ⇒ "any given element", we are not looking at it, hence no name
-- = ⇒ "is defined as"
-- 0 ⇒ that's zero
OK now let's look at a non-empty list. This part has two further cases. We look at the first element of the list. Either it equals to what we are counting, or not.
lefgNLista (x:xs) y | x == y = 1 + lefgNLista xs y
| otherwise = lefgNLista xs y
-- (x:xs) ⇒ A customary way to name a list pattern
-- y ⇒ The value we want to count
-- | ⇒ Pronounced "when"
-- x == y ⇒ Self evident
-- = ⇒ "is defined as"
-- 1 + lefgNLista xs y ⇒ Compute for the rest of list and add 1 
-- | otherwise = ⇒ Self evident
-- lefgNLista xs y ⇒ Just compute for the rest of list
So what is the type of this inferred by Haskell?
Prelude λ :t lefgNLista
lefgNLista :: (Num p, Eq t) => [t] -> t -> p
This is not as intimidating as it seems. You can read this as "when p is some kind of number, and t is some kind of stuff you can check for equality, the type is [t] -> t -> p". So this function works for Int, Double, (Int, Int) or any other type you can compare — even for other lists!
Prelude λ lefgNLista [[1,2], [3,5], [1,2]] [1,2]
2
What about Num p? Int is not the only type you can count with. You may need Integer if your lists are extremely long, or you may want to use your own fancy number-like type, but this is probably way too advanced at this point.

Haskell: Parse error in pattern x ++ xs

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.

What does (:) do in Haskell? [duplicate]

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

Haskell problems in a RPN caculator implementation

I'm trying to implement a RPN caculator in Haskell. It is an exercise from Learn You a Haskell.
Here's my code:
import Data.List
solveRPN :: String -> Int
solveRPN str = head $ foldl putStack [] (words str)
where putStack accumulator token
| token == "+" = pFunction (+)
| token == "-" = pFunction (-)
| token == "*" = pFunction (*)
| token == "/" = pFunction (`div`)
| otherwise = accumulator ++ [read token :: Float]
where pFunction function = (int $ init accumulator) ++ [function argu1 argu2]
argu1 = last accumulator
argu2 = last $ init accumulator
The function solveRPN first split a string into tokens. (ex:"4 3 2 + *"->["4","3","2","+","*"])
Then, one by one tokens are pushed into a stack. If it meets an operator, the last two items in the stack are processed by the operator and the value yielded is then put back into the stack. When the whole list is traversed, there's only one item left in the stack, and that's the answer.
There are some problems here:
In (int $ init accumulator) I want to cancel the last two elements in the stack. Is there any alternative to (int $ init accumulator)?
The code can't pass the compilation. GHC said "parse error on input ("
on this line: | token == "/" = pFunction (div). I suspect the problem might come from pFunction. Its parameter is an operator(or can I call it a function?) and I'm not sure if "function as the parameter of a function" is legal in Haskell. Is this legal? Is there any alternative?
I did some experiments in GHCi and found something strange:
Prelude> let plus = (+)
Prelude> :t (+)
(+) :: Num a => a -> a -> a
Prelude> :t plus
plus :: Integer -> Integer -> Integer
How come the type of plus is different from the type of (+)?
Thanks for your attention and patience. (:
In (int $ init accumulator)
Did you mean init $ init accumulator? That being said, you could write your own dropLast2 function, which does the same as init . init but traverses the list only once, something like
dropLast2 :: [a] -> [a]
dropLast2 [] = []
dropLast2 [_] = []
dropLast2 [_,_] = []
dropLast2 (x:xs) = x : dropLast2 xs
The code can't pass the compilation.
| token == "/" = pFunction (`div`)
You're using backticks (`) in order to use functions with two arguments as infix functions. However, by using parenthesis around div you try to cancel it right away, which is both a little bit off and a parser error. Simply use
| token == "/" = pFunction div
instead. However, there's one major thing of. div's type is
div :: Integral a => a -> a -> a
However, your accumulator is list of Float. div cannot possibly work on those. However, Float is an instance of the Fractional class, so you can simply use (/):
(/) :: Fractional a => a -> a -> a
and therefore get
| token == "/" = pFunction (/)
I did some experiments in GHCi and found something strange
(+) is part of the Num class. Your plus isn't part of any function, and GHC tries to infer its type. And then monomorphism restriction kicks in. See Type error while writing max function for further information.
Regarding your first question:
I get the impression that you are using lists the wrong way around. If you push an element on the stack, you should prepend it to the list using the : operator. Popping the top two elements then becomes drop 2 stack, which is much nicer, I think.
Doing it this way would also be more efficient, since : is a constant time operation while ++ is linear in the size of the first argument (i.e. your stack's size).

When destructuring tuples in Haskell, where can the elements be used?

I am reading a tutorial that uses the following example (that I'll generalize somewhat):
f :: Foo -> (Int, Foo)
...
fList :: Foo -> [Int]
fList foo = x : fList bar
where
(x, bar) = f foo
My question lies in the fact that it seems you can refer to x and bar, by name, outside of the tuple where they are obtained. This would seem to act like destructuring parameter lists in other languages, if my guess is correct. (In other words, I didn't have to do the following:)
fList foo = (fst tuple) : fList (snd tuple)
where
tuple = f foo
Am I right about this behavior? I've never seen it mentioned yet in the tutorials/books I've been reading. Can someone point me to more info on the subject?
Edit: Can anything (lists, arrays, etc.) be destructured in a similar way, or can you only do this with tuples?
Seeing your edit, I think what your asking about is Pattern matching.
And to answer your question: Yes, anything you can construct, you can also 'deconstruct' using the constructors. For example, you're probably familiar with this form of pattern matching:
head :: [a] -> a
head (x:xs) = x
head [] = error "Can't take head of empty list"
However, there are more places where you can use pattern matching, other valid notations are:
head xs = case xs of
(y:ys) -> y
[] -> error "Can't take head of empty list"
head xs = let (y:ys) = xs
in y
head xs = y
where
(y:ys) = xs
Note that the last two examples are a bit different from the first to because they give different error messages when you call them with an empty list.
Although these examples are specific to lists, you can do the same with other data types, like so:
first :: (a, b) -> a
first tuple = x
where
(x, y) = tuple
second :: (a, b) -> b
second tuple = let (x, y) = tuple
in y
fromJust :: Maybe a -> a
fromJust ma = x
where
(Just x) = ma
Again, the last function will also crash if you call it with Nothing.
To sum up; if you can create something using constructors (like (:) and [] for lists, or (,) for tuples, or Nothing and Just for Maybe), you can use those same constructors to do pattern matching in a variety of ways.
Am I right about this behavior?
Yes. The names exist only in the block where you have defined them, though. In your case, this means the logical unit that your where clause is applied to, i.e. the expression inside fList.
Another way to look at it is that code like this
x where x = 3
is roughly equivalent to
let x = 3 in x
Yes, you're right. Names bound in a where clause are visible to the full declaration preceding the where clause. In your case those names are f and bar.
(One of the hard things about learning Haskell is that it is not just permitted but common to use variables in the source code in locations that precede the locations where those variables are defined.)
The place to read more about where clauses is in the Haskell 98 Report or in one of the many fine tutorials to be found at haskell.org.

Resources