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>
This commit is contained in:
449
hpr_transcripts/hpr2808.txt
Normal file
449
hpr_transcripts/hpr2808.txt
Normal file
@@ -0,0 +1,449 @@
|
||||
Episode: 2808
|
||||
Title: HPR2808: Haskell function types
|
||||
Source: https://hub.hackerpublicradio.org/ccdn.php?filename=/eps/hpr2808/hpr2808.mp3
|
||||
Transcribed: 2025-10-19 17:05:18
|
||||
|
||||
---
|
||||
|
||||
This is an HPR episode 2008 and 2008 entitled Haskell Function Types.
|
||||
It is hosted by Tuku Toroto and is about 24 minutes long and carrying a clean flag.
|
||||
The summary is Tuku Toroto gives over new Function Types 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, this is Tuku Tuku Toroto and you are listening to the HAKER POTTER CRADY.
|
||||
Today's episode will be about Function Signatures in Haskell.
|
||||
Again, this is something that I should have done ages ago.
|
||||
But once again, better late than never.
|
||||
So Haskell is a static language, which means that when it's compiled, the compiler checks the program for type errors.
|
||||
So, it makes sure that you are not mixing for example strings and numbers.
|
||||
And for that, it needs types.
|
||||
Type is a definition of what kind of values can be used.
|
||||
Typical ones are in the string, text, bool and so on.
|
||||
There's quite a lot of them in the Haskell.
|
||||
And of course, new ones can be defined by the programmer.
|
||||
And type names always start with the upper case level.
|
||||
So then Haskell does type inference, meaning that if you choose so,
|
||||
you can omit type declarations completely.
|
||||
You don't have to tell Haskell that type of this function is something.
|
||||
You just can omit those completely and Haskell will try and figure out what kind of types would work for that.
|
||||
But it's helpful for the programmers if you are writing type declarations out.
|
||||
Because then they can more easily check from the source code.
|
||||
But what kind of type some function takes.
|
||||
And also, it instructs Haskell compiler that this function should have these types.
|
||||
Otherwise, if you don't specify that, Haskell will try to figure out what's the type signature.
|
||||
Sometimes it works, usually it works.
|
||||
But at the point where you make a mistake, then the Haskell compiler will try to figure out the type
|
||||
and it might give you a compiler error somewhere completely different place.
|
||||
So you should write type declarations at the top level of your program,
|
||||
meaning that all your functions should have types in them.
|
||||
And the type declaration is written as a name of the function.
|
||||
And colon, colon, and then types that it takes.
|
||||
So, for example, the simple, I won't be talking that much about the code in this,
|
||||
this, this or that will be talking more about the signatures.
|
||||
And what are the things you can do with those and what they tell you about the functions.
|
||||
So the simple, simple case is that you could have a function called add,
|
||||
that takes an index, two integrals, and produces an integer.
|
||||
And this is, as a type declaration, that declaration is written on top of the function,
|
||||
function definition.
|
||||
So that declaration for this type of function will be add, colon, colon,
|
||||
integer, arrow, integer, arrow, integer.
|
||||
So it takes two integrals and it produces value of inverter.
|
||||
And you don't have to have specific types.
|
||||
Sometimes you can have, you can mark that anything calls here.
|
||||
For example, if you had one another made up example,
|
||||
you would have a function that has signature of choose, colon, colon,
|
||||
a, arrow, a, arrow, bullen, arrow, a, and a is a lower case here.
|
||||
So, it, that means that this function choose takes two values of type a,
|
||||
which can be anything, a bullen, and it will produce a value of a.
|
||||
And a is always the same type in this function.
|
||||
It can be anything, but it's always the same in, like you cannot mix,
|
||||
you're going to put different types in the a.
|
||||
And we don't know anything about the a.
|
||||
It can be absolutely anything, which means that we also can do much inside
|
||||
in the true, of choose function with the a.
|
||||
Basically, we add even two a's and bullen,
|
||||
and based on that bullen, we are returning in the line of those a's.
|
||||
So, if we want to add a bit more functionality in that case,
|
||||
in a case where we don't have a specific type,
|
||||
we can use something called a bullen morphism.
|
||||
So, if you remember the at function,
|
||||
that we mentioned a couple of minutes ago,
|
||||
it only works, it only works within that case.
|
||||
You cannot use it with the float.
|
||||
You would, of course, define add f, that works with the float,
|
||||
and then some add i that works with the imaginary numbers and so on.
|
||||
But it would be kind of silly,
|
||||
because then the programmer would have to remember that
|
||||
here I'm adding in that, so I have to use add and here I'm using float,
|
||||
so I have to use add f.
|
||||
So, we can define that by using a type constraint.
|
||||
That means that we are writing it,
|
||||
the signatures would be add colon colon, open current,
|
||||
uppercase num, over this a, closed current,
|
||||
sad arrow, a, arrow a, arrow a.
|
||||
So, this means that a is constrained to be an instance of num,
|
||||
and add function takes two a's and produces a.
|
||||
And num in this case is a by-class that defines some functions
|
||||
that every instance of num implements.
|
||||
So, you know that if you are given, if your function takes an a,
|
||||
you don't know, you don't know exactly what it is.
|
||||
But you know that because it's a num,
|
||||
it has some functions that you can use on it.
|
||||
And num defines plus, minus,
|
||||
multiply, multiplication, negate, ups, sigma, and from index.
|
||||
So, it's some very, very basic number type of arithmetic.
|
||||
And I'm going to talk about type classes,
|
||||
another time that really need a concept,
|
||||
but grabbing them into this episode will make this a bit too long, I think.
|
||||
So, if you have a by-constraint,
|
||||
that is an uppercase num a, sad arrow,
|
||||
means that everything, everything in the type,
|
||||
the type signature a is always a num.
|
||||
And you can have, of course, multiple type constraints.
|
||||
You can say that num could be num.
|
||||
You could say that a has multiple constraints,
|
||||
or you could have that something that a is constrained
|
||||
to something and b is constrained to something.
|
||||
And we are not using b in this case, but you can have multiple,
|
||||
multiple type parameters.
|
||||
So, that is how you can use pretty generalized functions.
|
||||
And the cool thing is that our num,
|
||||
our ad function will work for every num instance.
|
||||
So, if somebody comes with a new data type,
|
||||
that implements, that has an in-the-instance num,
|
||||
our function will work with that, no problem.
|
||||
If, okay, if that num instance is written properly.
|
||||
Okay, then you can have parameterized functions,
|
||||
like, for example, you could have a function called first,
|
||||
that has a signature, signature of first,
|
||||
colon colon, open bracket a closed bracket, arrow may be a.
|
||||
And this is a function then that takes a list of a,
|
||||
that's the a inside of brackets.
|
||||
And a, again, can be anything.
|
||||
And it returns may be a.
|
||||
I talk about maybe in an early episode,
|
||||
with this type that is used to signify,
|
||||
value that might not be present.
|
||||
So, a can be anything, again.
|
||||
So, you are given a list of a's
|
||||
and it returns may be an a.
|
||||
And may be an a can be nothing or just a.
|
||||
So, in case you are given a list of,
|
||||
that is, at least one element,
|
||||
this will presume to,
|
||||
presumably, return the first element of that list.
|
||||
That's just a.
|
||||
But if you are given an empty list,
|
||||
this wouldn't crash,
|
||||
but it would just return nothing.
|
||||
And if you want to use functions,
|
||||
again, this is something really basic
|
||||
that I should have brought up,
|
||||
this would have told ages ago.
|
||||
But when you are calling or applying a function,
|
||||
you don't need parenthesis.
|
||||
So, our at function can be called,
|
||||
just try to simply add one to.
|
||||
So, you don't need parenthesis.
|
||||
And this means, of course,
|
||||
that if you are changing functions,
|
||||
like you are, for example,
|
||||
you are calling one,
|
||||
you want to add more things.
|
||||
You can write it as a,
|
||||
add one dollar sign,
|
||||
add two, three.
|
||||
And the dollar sign is there for the application order.
|
||||
It instructs that,
|
||||
first you evaluate the right side,
|
||||
add two and three,
|
||||
and then you use that value
|
||||
in the evaluation of the left side,
|
||||
at one.
|
||||
So, you are basically,
|
||||
you could use parenthesis,
|
||||
you could write that in the,
|
||||
you know, add one,
|
||||
open parenthesis,
|
||||
add two, three,
|
||||
close parenthesis,
|
||||
and the result will be identical.
|
||||
Six in both cases.
|
||||
And it's a, again,
|
||||
a bit of a personal preference,
|
||||
which one?
|
||||
You two use,
|
||||
I usually opt for using,
|
||||
a lot of times.
|
||||
Sometimes,
|
||||
it is easier to parenthesis.
|
||||
But it's good to know that there are options.
|
||||
And there's a one thing that really
|
||||
took some time to get used for me,
|
||||
is that you don't use parenthesis at all,
|
||||
in a function call.
|
||||
You just write the function name,
|
||||
and then you write the parameters.
|
||||
There's a,
|
||||
another need,
|
||||
concept in Haskell is the
|
||||
part of the application.
|
||||
So, you can,
|
||||
you can call function
|
||||
with less parameters,
|
||||
that it expects,
|
||||
and it won't cause,
|
||||
it won't cause a runtime error.
|
||||
So, example, you could define.
|
||||
If we have defined that,
|
||||
add function,
|
||||
we could define another function.
|
||||
Say, add lots,
|
||||
equal at thousand.
|
||||
So, we are calling add,
|
||||
our add function,
|
||||
that it's set two parameters,
|
||||
the single parameter.
|
||||
What happens here,
|
||||
is that,
|
||||
it will automatically,
|
||||
generate us a,
|
||||
when you're calling add,
|
||||
with the set a single parameter,
|
||||
instead of runtime error,
|
||||
we are going to get a new function back.
|
||||
And this function works,
|
||||
exactly like,
|
||||
add function,
|
||||
with the,
|
||||
that has been,
|
||||
that has the first parameter,
|
||||
thousand.
|
||||
So, now that we have,
|
||||
our add lots,
|
||||
that equals to add thousand,
|
||||
we can use our add lots to,
|
||||
just call add lots five.
|
||||
And this is equal to calling,
|
||||
add thousand five.
|
||||
So, you can easily,
|
||||
easily create new functions.
|
||||
And,
|
||||
for example,
|
||||
sometimes I like to use this,
|
||||
in a way that,
|
||||
I have some,
|
||||
general function,
|
||||
that takes our,
|
||||
some sort of configuration,
|
||||
and then some,
|
||||
some sort of parameters,
|
||||
that instructs,
|
||||
that uses,
|
||||
and then,
|
||||
that parameter,
|
||||
configuration results,
|
||||
to some value.
|
||||
For example,
|
||||
if I have a,
|
||||
if I had a game,
|
||||
where you have a building,
|
||||
and I wanted to know,
|
||||
a cost of a building,
|
||||
I would have a,
|
||||
general function,
|
||||
that would have a,
|
||||
list of those building costs,
|
||||
and then it would take a,
|
||||
name of the building,
|
||||
and result would be the cost of the building,
|
||||
it would call,
|
||||
through the list,
|
||||
find the building,
|
||||
return the cost of the building.
|
||||
I can use,
|
||||
this partial application,
|
||||
to create a,
|
||||
function,
|
||||
that takes the,
|
||||
general configuration,
|
||||
that is used in everywhere in the program,
|
||||
and afterwards,
|
||||
I have to test that,
|
||||
configuration,
|
||||
into the function name,
|
||||
or,
|
||||
because I have that,
|
||||
new function,
|
||||
that has been,
|
||||
sort of configured,
|
||||
to use,
|
||||
that,
|
||||
list of buildings.
|
||||
So I can just call,
|
||||
that,
|
||||
new function,
|
||||
with,
|
||||
name of the building,
|
||||
and it will give me,
|
||||
the cost of the building.
|
||||
Completely made up,
|
||||
explanation,
|
||||
but,
|
||||
that's,
|
||||
that's a one,
|
||||
one way,
|
||||
I could use this.
|
||||
And this,
|
||||
this is called,
|
||||
carrying,
|
||||
so,
|
||||
Wikipedia says that,
|
||||
in mathematics,
|
||||
and computer science,
|
||||
carrying is the technique,
|
||||
of translating,
|
||||
the evaluation,
|
||||
of a function,
|
||||
that takes multiple arguments,
|
||||
into evaluating,
|
||||
a sequence of functions,
|
||||
each,
|
||||
with a single argument.
|
||||
There was some,
|
||||
mathematics,
|
||||
mathematics and code,
|
||||
I think,
|
||||
I think he was called,
|
||||
Howard Curry,
|
||||
who,
|
||||
came up with this,
|
||||
and,
|
||||
a bit earlier,
|
||||
some,
|
||||
another mathematics and code,
|
||||
search single,
|
||||
came up with,
|
||||
the same idea.
|
||||
So,
|
||||
if,
|
||||
if the,
|
||||
Curry wouldn't have,
|
||||
I don't know why,
|
||||
it's the,
|
||||
why,
|
||||
why, this is,
|
||||
named as,
|
||||
Curry,
|
||||
Howard Curry,
|
||||
because,
|
||||
if it were,
|
||||
named after him,
|
||||
we would,
|
||||
we wouldn't be called,
|
||||
talking about,
|
||||
thinking,
|
||||
which,
|
||||
I think it would,
|
||||
yeah,
|
||||
funny,
|
||||
but, in any case,
|
||||
you can do part of your application,
|
||||
and,
|
||||
the,
|
||||
all of the parameters matter,
|
||||
as they are evaluated,
|
||||
from left to right.
|
||||
So,
|
||||
some,
|
||||
sometimes,
|
||||
it makes sense,
|
||||
to,
|
||||
dig the,
|
||||
parameter,
|
||||
order,
|
||||
a bit more,
|
||||
then,
|
||||
then,
|
||||
you,
|
||||
then,
|
||||
what I,
|
||||
was used to,
|
||||
according without,
|
||||
another images,
|
||||
because,
|
||||
if you have to,
|
||||
always,
|
||||
fly all the parameters,
|
||||
you don't,
|
||||
the order of the parameters doesn't really matter,
|
||||
but,
|
||||
here,
|
||||
because you don't have to,
|
||||
fly all the parameters,
|
||||
then,
|
||||
order start mattering a bit more.
|
||||
For example,
|
||||
if I had a,
|
||||
function plant broadcast,
|
||||
that take a list of broadcasts,
|
||||
auto and produces a list of portcasts. I could if that function is called find
|
||||
portcasts. So find portcast has a signature of list of portcasts text list of
|
||||
portcasts. So I could define a new function called search that equals to find
|
||||
portcast, loaded portcasts, loaded portcasts, a list of portcasts that came from
|
||||
some way, not in part of some way. And then I could use that function as a my
|
||||
portcast equals search to turbo. And that would search from that original list of
|
||||
portcasts, all the portcasts are made by me. But if the parameter order would be
|
||||
other way around in the find portcast function, it would first take the name and
|
||||
then the list of the portcasts, this method group verb. Okay, and then functions
|
||||
as types. Functions themselves are also types. So and they can be used as values. So
|
||||
you can you have if you have a function, it can be done a function and if you
|
||||
have a function and also a function can take another function as a parameter. One
|
||||
very common function that task is a filter. And it has a signature of filter,
|
||||
colon colon, open turns, R a, arrow, rule, close turns, arrow, open bracket,
|
||||
A, close bracket, arrow, open bracket. I'm sorry, let me do that again. So filter has
|
||||
a signature of filter, colon colon, open turns, A, arrow, rule, close turns, arrow,
|
||||
open bracket, A, close bracket, arrow, open bracket, A, close bracket. So filter is a
|
||||
function that takes two parameters. First parameter is a function that has type of A,
|
||||
arrow, rule. And the second parameter is a list of A. And it will return a list of
|
||||
A. So you need to have a two functions that have a
|
||||
maxing A. A can be anything, but it has to be same on both of those functions in the
|
||||
filter and in and in that parameter that filter breaks. And what the filter does is that it
|
||||
will apply that function that was given to every element in the list. And for every element
|
||||
that evaluates to, for every element that the function evaluates to true, it will return
|
||||
as a new list. So it has a name implies it is used to filter a list with a given function.
|
||||
It will find all the functions, all the elements in the list that will return true when given
|
||||
to that parameter function. You can use that for example, writing a filter, hot, open
|
||||
bracket, one dot dot, then close bracket. This will produce a list of hot numbers in a
|
||||
range of one to ten. And the last thing I'm going to call it today is the anonymous functions.
|
||||
Sometimes you need function to pass in as a parameter, like in the previous case, but you
|
||||
don't want to define and give it a name. What be that you are going to use it only once,
|
||||
or it is so short that it does not really need a name, it doesn't run having a name. So
|
||||
photos cases we have a long dot, or anonymous functions. And the syntax is for one function.
|
||||
It is a, for example, if you are going to use in the filtering example previously, we
|
||||
will want to filter all the hot numbers that are picket and file. We could write it in a
|
||||
following way. Filter, open parent, slash x, arrow, hot, x, ampersand, ampersand, x created
|
||||
then five, close parent, open bracket, one dot dot, then close bracket. So here we are, here
|
||||
we will be defining an anonymous function that takes a single parameter, x, and checks
|
||||
that the x is hot, and that x is created and five. If those both are true, then the value
|
||||
of the function is true, and this we use to filter all the hot numbers created and five
|
||||
in a range from one to ten. And you don't have to specify types here, has can will figure
|
||||
them out for you. So the syntax is a slash parameters, arrow and body, and you can have multiple
|
||||
parameters in the function. There are just separated by the spaces. And often you have
|
||||
to wrap this thing, you know, parenthesis when you're passing it in so that the hospital
|
||||
compiler knows where the anonymous function starts and where they pay it ends. Okay, that's
|
||||
it for today. If you have any questions or comments or corrections, easy way of catching
|
||||
me is either email or at the fediverse where I'm to tour at masterton.so also, or you
|
||||
can even, even better you can make your own hack-a-pattered radio episode. Okay, thank you
|
||||
for listening. Bye-bye.
|
||||
You've been listening to hack-a-pattered radio at hack-a-pattered radio.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 HPR listener like yourself. If you ever thought of recording
|
||||
a podcast, then click on our contributing to find out how easy it really is.
|
||||
Hack-a-pattered radio was founded by the Digital Dove Pound and the Infonomicon Computer Club,
|
||||
and is part of the binary revolution at binrev.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 status, today's show is released on the creative comments,
|
||||
distribution, share a light, 3.0 license.
|
||||
Reference in New Issue
Block a user