Files
hpr-knowledge-base/hpr_transcripts/hpr2888.txt
Lee Hanken 7c8efd2228 Initial commit: HPR Knowledge Base MCP Server
- MCP server with stdio transport for local use
- Search episodes, transcripts, hosts, and series
- 4,511 episodes with metadata and transcripts
- Data loader with in-memory JSON storage

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-26 10:54:13 +00:00

233 lines
14 KiB
Plaintext

Episode: 2888
Title: HPR2888: Pattern matching in Haskell
Source: https://hub.hackerpublicradio.org/ccdn.php?filename=/eps/hpr2888/hpr2888.mp3
Transcribed: 2025-10-24 12:47:03
---
This is HPR episode 2008-188 entitled, pattern matching in Haskell, and in part on the series, Haskell, it is hosted by Tuku Toroto, and in about 21 minutes long, and Karima Clean Flag.
The summary is, Tuku Toroto talks about one of their favorite features in Haskell.
This episode of HPR is brought to you by an honesthost.com.
Get 15% discount on all shared hosting with the offer code, HPR15, that's HPR15.
Better web hosting that's honest and fair at an honesthost.com.
Hello, you're listening to The Hague Public Radio, and this is Tutu Toroto talking about pattern matching in Haskell.
This is one of those features that when I saw in action, I was completely sold pretty much immediately.
So, the basic idea is that if value constructors are for making data, then the pattern matching is taking that data apart roughly.
So, simple example.
We have a Boolean, type Boolean, that has two value constructors.
True and false.
True makes a Boolean and false makes a Boolean. They have different data in them.
So, then if we have a function that takes a Boolean as a parameter, we can match against that value constructors.
If something, we have a function called Boolean string that takes a Boolean and returns a string.
And we could write it in a way that it uses if inside of it.
So, Boolean string n equals if n, then Quotation, true and Quot, else Quot, false and Quot.
So, when you call it with a true, it returns true as a string.
And with a false, it returns false string.
And the choice was made by the if statement inside of the function.
We can remove that if statement by doing pattern matching on the parameter.
So, the thing that is the same, it's still pooled string.
But it is written as pooled string, true equals Quot, true and Quot.
Pooled string false equals Quot, false and Quot.
So, it looks like there's two definitions of the function.
One for the true and one for the false parameter.
Actually, but in reality, there's a one definition, but two cases.
You can have more complex data in the pattern, but it still works in the same way.
So, for example, if we have a function called e-speak that is given a maybe int and it returns a string.
So, maybe it's the data type that has two value constructors.
It has nothing and maybe a.
So, nothing signifies that there is no data available and just a indicates that there's a value available.
And a is whatever type we have declared, declared it to be in our case, it's the int.
So, we can match those two value constructors and write it as e-speak, nothing equals Quot, not at all and Quot.
e-speak, open pattern, just one, close pattern equals Quot, just perfect and Quot.
And e-speak, open pattern, just n, close pattern equals.
If n is less than 10, then Quot, just lightly, and Quot, L is Quot, definitely is end Quot.
So, we have three cases, nothing that is covered by the e-speak, nothing equals.
And that will handle the case when you call this with nothing.
Then there's a e-speak, just one.
This will handle the specific case, then we are calling this, and the parameter is just one.
And then there's a more general case, e-speak, just n.
This will match the case that we have, even match all the rest cases.
So, n will capture the value that was given to the chest, and it will be available as a named parameter, named value inside of the function.
And order where you define this is important.
And if we had that two of these last ones, switch places, we would define just n before the case, just one.
Then the just n would take, would trigger when we expected that just one to trigger.
So, the program will call functions, prove them in order to find each one, the first one that matches.
So, this is an example how to do it.
How to match to some value of constructor and catch a data that was used.
Use to construct the data into a parameter.
So, e-speak, open-paren, just n, close-paren, e equals, and then the definition.
The pattern matching isn't limited to algebraic data types, those examples that we went through before, for earlier.
But it works for records to records itself.
Data types where we have one value constructor, and then there's a multiple one or more records, sorry, fields with names.
So, if you haven't been following the show notes, now it will be a good time to go ahead and do a few things.
This might be a tricky to follow.
But, to be clear, I'll record, we will, for example, this could be a customer record.
Open-paren data, customer, e equals, customer.
Open-procket, curly-procket.
Customer name, double-colon string, comma-customer-discount-percent, double-colon-table, comma-bid-customer-table-colon-bore-close-curly-procket.
So, now we have a type, customer, that has one algebra constructor, also called customer, that has three fields.
Customer name, that is string, customer-discount-percent, that is double, and with customer, that is poor.
So, whenever we have a customer, we know that it has these three values available.
Then we have a function called total fee.
This is a made up example, that calculate what a total fee is based on the cost and the discount percentage.
First, we have a special case, total fee, bill-cost-it-open-paren-customer-open-curly-tracket-with-customer-equals-through-close-curly-fracket-close-paren-equals.
And then, inside of the definition, bill-times-sylip-on-mime-times-customer-discount-percent-cast.
So, there's a lot of coin on here.
So, the total fee is taking two parameters.
First one, bill-is-a-table.
Second one, cost-over, we are matching that to a case where the rib-customer record is true.
If that record, if that field is false, this definition won't get called.
So, this one will only be called when the rib-customer is set true.
And then, we are using that cost at the beginning to catch the value of the customer into the parameter named cost.
And then, we can use those values inside of the function to multiply the bill-times-sylip-on-mime-times-customer-discount-percent-cast.
Regular case for the function is defined as a total fee, bill-cast equals bill-times-customer-discount-percent-cast.
Meaning that if the rib-customer is false, this will get called.
And we are going to just multiply the bill by the discount percentage.
There's no extra discount that is given to the rib-customer.
Okay, then, the special case list, take-and-tip-hatamets-2.
I think I showed this.
I only used this when we were talking about the records on the way back, but didn't explain that closely.
So, we can have a...
We were doing the matching the customer for example,
a lot of constructors of the Boolean.
We can match in the same way list.
And the syntax is that if you have a list of at least one item that you want to match,
you would just find it as an open-paren-x-colon-xs-close-paren.
The names of variables aren't important.
What is important is that colon in the definition.
So, in this case, x will be the first item of the list and xs will be the rest of the list.
There might be a zero item there, then it's an empty list,
or there might be a Hunos-how-many item there, but it's a list.
If you want to match a list that has at least two items,
we could find it as an open-paren-x-colon-y-colon- underscore-close-paren.
Now, x is a first item, y is the second item,
and that underscore is the rest of the items.
But we are not interested in using those.
So, we are matching them with the underscore.
That's a wild card that matches anything,
but it doesn't find it into the name.
Now, we have access only the two first items of the list,
of the list, and the fifth vegan of the access.
And, of course, if you want to match completely empty list,
there's an open-pricot-close-pricot that matches the empty list.
So, list of exactly one item would be an open-paren-x-colon-open-pricot-close-paren.
Because now, we are matching a first item, it matches to a one item,
and then it matches to the empty list.
So, list where there's a head, and the tail is empty list.
And, like I said, the underscore- underscore match has to everything,
but it doesn't point the value to a name.
And, where items to use this is when I need to match,
I mean, where I don't care, value of something,
then I'm using underscore.
I could, equally, use some made-up name there,
like N, or anything,
but then, if I'm not using that name in the function,
then the compiler will assume you're warning that you have a value
that is not being used.
And, I think that's a good idea,
because that might catch some bugs,
or thought errors, or what you call those.
So, I don't, either I aim to try to only declare variables,
or values that I actually need,
and if there's something that I don't need, I use underscore matches.
So, for example, we could use that list matching
to count how many items there are in the list.
And, we would define that as the signature would be count,
the bulk colon, open, bracket A, closed bracket, arrow int.
This means that our count function takes a list,
takes a list of anything,
hence the analog SA, and returns an int.
If this one can take a list of integers,
list of strings, list of moulins, list of anything.
And, the definition for this one is count,
open, bracket, closed, bracket equals zero.
So, when we call our count with an empty list, it returns zero.
And, then, the network case, count, open, turn, x colon,
x colon, x-s, closed, turn equals one plus count, x-s.
So, what this does is that it takes the first element of the,
our list, and then takes a count of the rest of the list,
and acts one to that.
So, it will call count again,
and again, and again, until it reaches a point
where the empty list is handed to it,
and in that case, it returns zero,
and then it will add up all those ones together.
So, this is one way of counting elements on a list.
You can also do a common example is a Fibonacci.
That's a sequence of numbers where every number is defined
as a sum of two previous numbers.
And, the first two ones are zero and one.
So, the sequence calls cause something like zero, one, two, three,
five, eight, thirteen, and so on.
And, we can have it as a different as following.
We have a signature Fibonacci.
The focal length int are all int.
So, you give int, and you get int back.
And then the actual definition is Fibonacci zero equals zero.
Fibonacci one equals one.
These are the two first numbers.
So, when you call it zero, you get a zero,
and when you call it with one, you get a one.
And then there's a general case Fibonacci n equals Fibonacci n minus one
plus Fibonacci n minus two.
So, when you call it with any other number,
that a number that is a zero, one, it goes to this central case
and goes itself twice and acts up the numbers together.
Here's a slight problem that if you call it
with a for example minus one, it will never, never, ever terminate.
It will just run until the, until, well, actually,
it will run until you exceed the range of the integrals.
When you get a big enough number, that it will issue a random error.
But here, here there's a problem that if you call it with a negative number,
it will keep running.
But with positive numbers, this one works.
And so far, they have been doing pattern matching on function parameters.
There's a case expression that does the same thing, but inside of a function.
But the truth for that are exactly, exactly the same.
You can do exactly the same pattern matching tricks that were shown above,
earlier, but with inside a function.
For example, if we wanted to define our Fibonacci
using the case, it will be, the other signature will still be the same,
but the definition will be Fibonacci n equals case n of 0 arrow 0, 1 arrow 1,
n arrow Fibonacci n minus 1 plus Fibonacci n minus 2.
And that's it.
So the case expression works in a way that there's a case.
But what you're matching against off and then the matches underneath.
And every after every match, there's an arrow with a value that that case will produce.
And even here, if you miss a case, the compiler will helpfully complain to you
that this match isn't exhaustive.
For example, if we forgot the last case of the Fibonacci example,
and match it only to the 0 and 1, the compiler will say that you are missing the.
I don't actually remember exact wording, but it would say that you are missing a case
where you, that is different than 0 and 1.
Which is pretty handy that it even detects that you are not matching to all indexes.
So the advantage of this is that you can remove if statements that, well,
that's a subject maybe, but I like that there's a, the less there is an if statement,
the better in my opinion, because I mean, you still,
of course, you need to do the choices, but every time you have an if statement,
it has a print and then you have a, for example, if you have a two consecutive if statements
in your code, that means that there's a full tax through that code.
And if you have three, then you have a eight tax through that code.
And you get really complicated to figure out what's going on and how everything plays together.
Having those in the pattern matching, custom trim, remove the complexity,
but it makes it linear.
It's easy to see that with this case, you're doing exactly these things.
Another advantage is that compiler will help you to catch the cases where you are,
where you missed a match.
Like there's a case that you haven't handled.
Okay, that's all about this.
If you have any questions, comments or feedback, tell me,
I'm the best way to catch me if, no, there's either email or in Fediverse,
where I'm to do it at most, but that's the social.
Thanks a lot.
You've been listening to Heckapublic Radio at HeckapublicRadio.org.
We are a community podcast network that releases shows every weekday, Monday through Friday.
Today's show, like all our shows, was contributed by an HBR listener like yourself.
If you ever thought of recording a podcast, then click on our contributing to find out how easy it really is.
Heckapublic Radio was founded by the digital dog pound and the Infonomicon Computer Club,
and is part of the binary revolution at binwreff.com.
If you have comments on today's show, please email the host directly,
leave a comment on the website or record a follow-up episode yourself.
Unless otherwise stated, today's show is released under Creative Commons,
Appropriation, ShareLight, 3.0 license.