Reputation: 537
In order to get a head start into the path of Haskell, I chose the book by one of its creators Hudak. So, I am going through the gentle introduction to Haskell.
I got stuck at trying to understand the following statement:
Technically speaking, formal parameters are also patterns but they never fail to match a value.
From my little but relatively greater habituation with languages like C (or let's broadly say as non-functional languages), I could form that formal parameters are the arguments in the definition of a function. So, suppose there were a function like the following in C:
int func_add(int a, int d)
then passing a value of some other type like string will be a failure in pattern matching if I am correct. So calling func_add
as func_add("trs", 5)
is a case of pattern mismatch.
With a heavy possibility of an incorrect understanding or interpretation this similar situation can occur very well in Haskell as well when a piece of code calls a function by passing arguments of different types.
So, why is it said that in Haskell formal parameters are irrefutable pattern matching?
Upvotes: 12
Views: 1615
Reputation: 477607
What you describe is not a pattern, it is a type. Haskell has types as well, and these are resolved at compile time. Each type can have several patterns. For example a list is defined as:
data Color = Red | Green | Blue | Other String
Now we can define a function foo
:
foo :: Color -> String
foo Red = "Red"
foo Green = "Green"
foo Blue = "Blue"
foo (Other s) = s
The elements in boldface are all patterns. But these are not irrefutable: the first one will check if we have given the function a Red
, the second whether we have given it Green
, the third if the value is Blue
, and finally we have a pattern (Other s)
that will match with all Other
patterns (regardless what the value of s
is), since s
is a variable, and a variable is an irrefutable pattern: we do not perform any checks on the value of the string.
Mind that these checks are done at runtime: if we would however call foo "Red"
, we will get a type error at compile time since the Haskell compiler knows that foo
has type Color -> String
.
If we would have written:
foo :: Color -> String
foo c = "Some color"
foo Red = "Red"
c
is an irrefutable pattern: it will match any Color
object, so the second line foo Red
will never match, so c
is an irrefutable pattern.
Upvotes: 10
Reputation: 233377
In Haskell, you can define types in various ways. One of these is to introduce a sum type, like this:
data FooBar = Foo Int | Bar Bool
You could attempt to write a function like this, using pattern matching:
myFunction (Foo x) = x
That would, however, be a partially matched function, and if you try to call it with myFunction (Bar False)
, you'd get an exception.
You can, on the other hand, also define single-case sum types, like this:
data MyInt = MyInt Int
Here, you can write a function like this:
myFunction' (MyInt x) = x
Here, you're still using pattern matching, but since there's only a single case, this is a complete match. If the calling code compiles, the match can't fail.
The above MyInt
is really only a wrapper around Int
, so you could say that if you write a function that takes an Int
, like this, it's the same sort of pattern matching:
myFunction'' :: Int -> Int
myFunction'' x = x + 42
While Int
doesn't have a value constructor that you can use to pattern-match on, x
is a pattern that always matches an Int
value. Therefore you can say that a function argument is a match that always succeeds.
Upvotes: 3
Reputation: 11372
No, passing a value of some other type is not a failure in the pattern matching. It's a type error, and the code won't even compile. Formal parameters are irrefutable patterns for a well-typed program, which is the only kind of program that the compiler allows you to run.
Upvotes: 7