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 (:).
In Haskell, lists are a homogenous data structure. It stores several elements of the same type. That means that we can have a list of integers or a list of characters but we can't have a list that has a few integers and then a few characters. And now, a list!
There is a function in Haskell that takes first n elements of user-supplied list, named take . The syntax is: function-name arg1 arg2 . So, take takes first 1000 elements from an infinite list of numbers from 0 to infinity.
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
.
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