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:
196
hpr_transcripts/hpr2758.txt
Normal file
196
hpr_transcripts/hpr2758.txt
Normal file
@@ -0,0 +1,196 @@
|
||||
Episode: 2758
|
||||
Title: HPR2758: Haskell - Data types and database actions
|
||||
Source: https://hub.hackerpublicradio.org/ccdn.php?filename=/eps/hpr2758/hpr2758.mp3
|
||||
Transcribed: 2025-10-19 16:25:54
|
||||
|
||||
---
|
||||
|
||||
This is HBR episode 2,758 entitled, Haskell, MaterType and MaterBase Action.
|
||||
It is hosted by Tuku Toroto and is about 43 minutes long and carrying a clean flag.
|
||||
The summary is brief summary on how to declare your own MaterType in Haskell and how to store Mater in MaterBase.
|
||||
This episode of HBR is brought to you by Ananasthost.com.
|
||||
Get 15% discount on all shared hosting with the offer code HBR15, that's HBR15.
|
||||
Better web hosting that's honest and fair at Ananasthost.com.
|
||||
Hello listeners, this is Tuku Toroto and you are listening to Hacker Public Radio.
|
||||
Today I am going to have a short episode of HBR15.com.
|
||||
Hello listeners, this is Tuku Toroto and you are listening to Hacker Public Radio.
|
||||
Today I am going to have a short episode about data and data types and data bases in Haskell.
|
||||
I have probably skipped over some basics when I started doing a service about Haskell game programming.
|
||||
But today I am going to go through over the data.
|
||||
There are two things that I am covering in this episode.
|
||||
Data types and very briefly and persistent library and that even more briefly.
|
||||
So the data in the beginning has nothing to do with the data bases.
|
||||
It's just about how you declare data types in Haskell.
|
||||
So data types are declared with the data keyword.
|
||||
And the simplest data type that I am thinking of can be declared as a data simple with a simple as a apokese.
|
||||
First level is apokese equals one again the first level is apokese.
|
||||
So data simple equals one is the simplest data type.
|
||||
It is a data type called simple that has such a single value one nothing else.
|
||||
You can use that by saying that my value equals one.
|
||||
And now the my value has a type of simple and its value is one.
|
||||
But this isn't particularly interesting.
|
||||
So if you want to have a more complex data type, you can declare it as a data color equals red pipe character that straight line pipe green pipe blue.
|
||||
This declares a data type color that has three possible values red, green, blue.
|
||||
And with this one you can say things like declare in a code you can say that color of grass equals green or color of my car equals blue.
|
||||
So this this color data type can have three possible values.
|
||||
It's like a enumeration in many other programming languages.
|
||||
Okay, so you can have multiple values that are alternatives for the alternative values for the data type.
|
||||
The third type is a data payment equals cash double or pipe character IOU text.
|
||||
So this one declares a data type payment that has two values one is cash that takes an additional parameter double or it has a value IOU that takes additional parameter of text.
|
||||
So with this one you can say things like for example, when you're doing a payment software you can say that customer payment equals cash 500 mean customer paid 500 or car payment equals IOU.
|
||||
So you can have a data data type that which value contains some extra.
|
||||
So you can you can add that small information it's not it's not anymore just a simple enumeration it has.
|
||||
So this one has two value constructors cash and IOU and both of them take one parameter cash takes a double and IOU takes a text.
|
||||
So not we got into the attaching more data we can also do something called parameter parameterized data types.
|
||||
These types are even more even more powerful one typical example is one that declares that some data or information might or might not be present.
|
||||
And it is declared as a data may be a is this time of low case equals nothing pipe just a.
|
||||
So this declares a data type maybe that is parameterized with a a can be anything in this case it has two value constructors first one is nothing signifying that there is no data present.
|
||||
And the second one is just a meaning that there's a value construct of just that takes a parameter a and a can be anything but a here is something you have to you have to declare the a when you're programming.
|
||||
So if you are for example if you are if you're doing an accounting software or cash payment software the payment might or might be present you can declare that customer payment type is a may be payment meaning that it can be nothing if payment hasn't been received or it can be just.
|
||||
Just cash double for example just cash 500 or just cash I owe you I back my data later.
|
||||
So you can start building a more complex higher up this and when you are dealing in the code with this this this data the Haskell and and you are for example you are checking that.
|
||||
You are you are writing a case statement which is written in a form of case customer payment of.
|
||||
And then on the next line nothing I wrote it right handling for the for the case that the payment hasn't been received and then on the next line just.
|
||||
X for example the existence important it just takes the value inside of the just and then the arrow and the handling of that case that the payment has been received so you can you can start doing things like where you have depending on the which value constructor has been used you can have different type of handling in the program and if you happen to.
|
||||
Forgot to handle one one one value constructor somebody may be at the new new value constructor in the data by the Haskell Haskell compiler will emit a warning that you haven't handled all the.
|
||||
The case is here the case missing here.
|
||||
And then you go and fix those places.
|
||||
Okay so these are this this this way of doing the data types is good when you have only small amount of fields but if you have a more data attached to more data to carry all carry in your code.
|
||||
For example you have a person you wouldn't want to try to remember if the seventh or eight fields the age of the person that gets.
|
||||
That gets to error from so in that case you can use record which are declared with the data keyword again so to declare a simple simple short record you can do like data person equals person.
|
||||
Call it pocket person name double colon text comma person age double colon age.
|
||||
This is a data that person that has a single value constructor also called person and that that the record has two fields person name that is a type of text and person age.
|
||||
That is type of age.
|
||||
So now when you're dealing with the code with a person you can just say you you can just say person name space your your variable for example customer and that will give you the name of that customer.
|
||||
And you when you are constructing instances of the person or you you can you can still say for example me equals person.
|
||||
So you don't have to specify the the fields that you are finding the values but if you want you can also say that me equals person.
|
||||
Call it pocket person name equals to the question marks comma person age equals thirty seven.
|
||||
This is this way this way you when you are creating a person it's easier to keep track of in which field the data comes into.
|
||||
And sometimes you want to have a for example in this case we had a age type sometimes you really wish to have a simple data type that has nothing fancy and that is basically a something that that looks like something that already exists but you want to make sure that some you are not making data.
|
||||
For example I could have a suicide in the person record and age in the person record code code code could be integrators and it would be easy to mix them because in itself doesn't know what it is.
|
||||
So I could we can declare new type that is a record of one field and that is declared as a new type age equals curly bracket get age double colon in curly bracket.
|
||||
So this declares a age record that has only one field get age so when you have a when you have a for example age what do you you have to and you want to use the underlying index in that you have to call the get age to get that outside.
|
||||
The advantage here is that it makes sure that you don't mix the suicide and age with it with each other and then compiler knows that this this new type only has a one one field.
|
||||
It can only have one field compiler but the compiler knows that this is a new type so it replace replace the age with it actually during the compile time so they isn't any over it is just by any performance.
|
||||
Okay so now that we have some data types we can do something with them but for example we cannot compare if two persons are same because there isn't function functions for that we cannot we cannot print them on this screen.
|
||||
So we would have to define those methods by hand and some of the common methods or functions sorry some of these common functions can be derived automatically we can we can just at the end of the data type declaration right deriving and then the regular parents show a comma read comma equal close to run.
|
||||
So this means that now the payment has is an instance of so read and equal so one means that you can print it on the screen you can if you have correctly formatted a string you can turn that into the payment and you can compare two payments if those are equal.
|
||||
There's some some auto functions that you can automatically do as not going to go through them now they are not important for understanding what we are talking about now.
|
||||
So this is this how you get your data files in the house. These are these are the bread and butter and if you want to start working with the database is especially in that I'm talking about.
|
||||
From the point of view of yes or because that's basically the only only thing I have been working with in ask I have been doing very little of anything else.
|
||||
So from now on it's all about yes or and the database library persistent by the yes or so the database is defined in the models file.
|
||||
It's called it it's usually research in the director of economic and it's called models.
|
||||
It is read at the compile time and it is used to generate data.
|
||||
So if you declare a table in the in the models file the compile time has to declare a creative data pipe that is named same as the database table.
|
||||
So if you and if you have the my friends my creations turned on like I have I have in the development environment when the program sounds the program that you just compiled it will automatically
|
||||
try and update the database. So if new tables have been created it will create them for you. If you have modified the existing table it will try to update the schema of the database.
|
||||
If you are just adding new columns it will work usually and if you are doing anything more complex it usually will not work and then you have to do it manually.
|
||||
So for example if you if you were to these examples are listed from the game that I have been talking about.
|
||||
So to declare a star system we just write on in that models file star system and with our separately lines underneath that name text code X in code Y in the database.
|
||||
So this defines star system record that has three fields star system name type of text star system code X type of in star system code Y which is type of in the tool.
|
||||
It's the derived data types always contain the name of the table and then the name of the field and then that together and when the persistent creates a database table it is star underscore system and has fields name code underscore X code underscore Y with correct database.
|
||||
And if you want to have a foreign sorry of course it has also the ID column that is the primary key of the of that table.
|
||||
If you want to have a foreign keys to referring to another table so you can do it like for example for the star we have a definition of star name text star system ID star system ID spectral that spectral type luminous glass luminous glass deriving soul read ego so this will define a table star and also the data type star.
|
||||
And it has the star system ID field in a database it's a star underscore system underscore ID and in the code is a star star system ID.
|
||||
And in the database it's type is at least in the case of a school light I think it's a indicator and in the code it's type is key star system and this this creature for any relationship from the star to the star system.
|
||||
So whenever you have a star it has to have a link to a existing star system and that link has to be valid.
|
||||
It also we also define the two fields spectral type luminous glass which are like a spectrally type of spectral type and luminous glass.
|
||||
And yes or of course a person sorry doesn't know what what what in Earth spectral type is so we have to tell it and we do that by defining a regular data type in a code.
|
||||
Data spectral type equals O pipe B pipe A pipe F pipe G pipe K pipe M pipe L pipe D deriving soul read EQ so now we have a regular data type spectral type that can have can have some one value.
|
||||
One value sorry one let the value that I just listed in the spectral type of the of the path but yes or doesn't sorry persistent doesn't know how to start this into the database so we have to use template ask her and add one more line into the code reading the derive persistent derive versus field.
|
||||
Quadition mark spectral type Quadition mark this during the compile time will instruct the compiler to derive some additional code that I'm not actually I actually don't know exactly what that will make sure that when the when you are trying to save a spectral type in a database in a column in a column.
|
||||
It will first turn it into the string and then store it into the database so that our spectral type column in the database is type of I think it's a watcher and when you are reading the star and it is from the database it will take that spectral type string and convert that into the spectral type value.
|
||||
And of course if you have something incorrect here for school hello world then the reading will fail and I think you the program might even crash at that point I'm not 100% sure it's been a month since I did that or it emits an error I think it will crash I should try that out at some point and the luminosity class is declared in the same way so you have a data luminosity class equals.
|
||||
IAP pipe IAP pipe IAP pipe IB pipe Roman numeral 2 pipe Roman numeral 3 and so on and deriving so really cool and derive versus field Quadition mark luminosity class Quadition class I mean Quadition mark so now you can store the luminosity class into the database.
|
||||
And you can store pretty big and complex data like this into in a single column but the problem is that it started as a string so if you want to search into that data it's going to be it's going to be slow so I usually try to break the things.
|
||||
At least the fields that I'm going to serve that I'm suspecting that I'm going to search by trying to break those into regular columns.
|
||||
Okay, and the last one example is a planet that is in the again in the model file.
|
||||
Defend as a planet name text position int stasas system ID stas system ID.
|
||||
This is just a foreign again owner ID, fashion ID, maybe gravity double system position stas system ID position and we're having so really cool.
|
||||
So this own own ID, fashion ID, maybe line defines that there's a column owner underscore ID that is type of int I believe and that has a that does not have a not null constraint.
|
||||
So this column in a database can be a frozen field.
|
||||
So this field in a database can be empty all the other fields has to has to be present so planet has to have a name it has a not now constraint in the database.
|
||||
And in the code the planet owner ID field in the record is type of maybe function ID and this maybe is the one that I talked earlier.
|
||||
So it has two possible values nothing and maybe key function.
|
||||
So it can be empty or it can contain the key of a function.
|
||||
And then there was another interesting line the system position stas system ID position.
|
||||
This are in the instruct the persistent that you want to create a unique index system position that has that is on columns.
|
||||
So this means that planet that this means that for any given far they can be only one planet at any given position.
|
||||
So you cannot have a mask colliding by accidentally sending them into the same position in the star system.
|
||||
So if we want to use this stuff in the code for example we want to create a solar system we can define a function create solar system equals two and then on a separate lines system ID arrow to the left insert dollar star system.
|
||||
So this will call will tell persistent that I want to insert into the database this star system record that has a name of solar so that has named solar system and coordinate zero zero so it's in the Oregon.
|
||||
And you don't have to tell the assistant better save it because it knows that it's a star system.
|
||||
I am it's a type of star system so it has to go into the star system table and then you can say and it will return a key star system.
|
||||
So it's the primary key of that record you just insert and that's you are saving in the system ID and then you in the save you can say star ID arrow to the left insert dollar star.
|
||||
So the system ID system ID that you got back on the previous insert key and we so we are telling that the spectra the type of the star is a key we are not storing the magnitude of the database.
|
||||
And again you are getting a star ID which is of type key star and then to final step is planet ID arrow to the left insert dollar planet code smart there record smart three system ID nothing 1.0.
|
||||
So planet earth is located in a solar system it's on a position 3 has a gravity of 1.0 G and has no or no currently it has nothing there.
|
||||
And to return all the data that we all these three keys that we created here the trending return parents system ID comma ID comma plant ID close parents so when you're calling the create solar system function it will create it will insert these three rows into the these three and it is in the database and it will return the IDs photo photos.
|
||||
And to all these one you have to you have to use the run dp function so in some way else you can say that rest out of the rest this is just a name of a
|
||||
variable you want to store the result of this function so rest arrow to the left run dp dollar create solar system.
|
||||
You can actually emit the dollar if you want and this will start the transaction create the solar system and commit the transaction.
|
||||
And you can have really complete complicated queries you can you can mix insert updates to delete what not and can have multiple functions being called and everything but at the top level where you want to start the transaction you have to have the run dp.
|
||||
The dollar that is in some of those places for example size system ID arrow left insert dollar star system solar system zero zero that dollar there is a I don't remember the correct name but basically what it does if you if you were to omit it the we will be calling insert function with the parameters star system solar system string string zero and zero.
|
||||
And insert will know what to do with all this data it needs a entity so we are using dollar to instruct that first evaluate the right side of this line and then call the insert with the result of that that thing.
|
||||
So it will it will create the star system and then call insert and give that star system data data into that.
|
||||
And then then the persistent will insert that record into the database.
|
||||
Or I will insert the star system into the database creating a record to the or off.
|
||||
You know actually how what would be the correct way of saying that but the bottom line is that the stars got saved into the database and you can later on go.
|
||||
So how do we actually go everything is the persistent has persistent has quite a lot of got quite a lot of functions that you can use.
|
||||
So the to load data the select list that takes two or two lists as a parameter first one is a information telling how to select.
|
||||
I mean by with by with with criteria this goes to the bare part of the SQL statement being generated and second list is a where you can order it for example.
|
||||
For example where you can order it so to load all planets we have we can just write planets are all to the left run dp dollar select list.
|
||||
A bracket planet gravity equals equals dot 1.0 close bracket open bracket ask planet E day close bracket.
|
||||
So this will load all planets which planet which private gravity is exactly 1.0 and order them by the primary key.
|
||||
And if you wanted to load everything from the table you could just write select list open bracket close bracket open bracket close bracket like you know parameters and the persistent would load the content of the whole whole table.
|
||||
But that will only work if the has has can somehow deduce from the surrounding code what what what pipe you want to have because because because of if you're not specifying any search parameters it cannot.
|
||||
From it cannot deduce from the search parameters what paper it should be handled but if later on you are accessing to are some data that is specific to the planet then it figures out that okay so you are loading a whole data database table and later on you are.
|
||||
Treating that as a list of planets so you therefore you must be loading a planet planet a table so the hospital can figure out quite a lot of.
|
||||
About what you are doing what you want to do without you specifically telling it what you want to do usually it works when it fails it gives you a really really funky error set might be a trick to.
|
||||
To drill down to drill down and solve so it's advisable to specify types as much as you.
|
||||
Well in a correct amount not too much not too little I usually specify types of the functions and that is enough for the has to one part.
|
||||
Okay if you want to load a single single pro or single entity there's a get so you you can just say planet are all to the left get planet I.D.
|
||||
Planet I.D. has to be a idea of a plant you are loading this does not return a planet it returns a maybe planet because.
|
||||
If you give a incorrect I.D. somebody has deleted the role it might not be any more so it returns you a maybe planet and then you have to.
|
||||
Account the fact that you may or may not have a planet at your disposal when you are dealing with the information and that's a that's.
|
||||
One more thing that I like about the system it says that hey part of it is you might or may not have this so treat this.
|
||||
And keep that in mind updating is done with update so and that takes a two parameters it takes a idea of the role you are updating and then it takes a list that is how you are updating so for example.
|
||||
If we have a planet called terror and we want to update it to be called hurt we can just say update planet I.D.
|
||||
Praket planet name equals dot quotation hurt quotation close bracket and that I find that into planet name.
|
||||
Earth in a row where the primary key is the planet I.D. that he just passed in and if you have noticed that.
|
||||
For example when we were comparing things we were using equals equals dot and then when we are finding we were using equals dot these are just how persistent has defined these functions because you cannot you cannot use regular equals or regular assignment here.
|
||||
So it has defined its own operators own functions that are usually they are the same as you would expect them to be.
|
||||
Repended with a dot no I can that with that right. I mean put to the end with a dot so regular comparison is a equals equals and in person it equals equals dot assignment is equals and in person to find this equals dot that's just that.
|
||||
So that's just that is the way of keeping track I'm keeping this separate that I call our assignments and the assignment calling the database.
|
||||
Okay I'm deleting is done with the delete function you can say delete planet I.D. that it's a new row from the database or you can use delete where that takes a list of.
|
||||
List of parameters so you can say delete there open bracket planet gravity greater than dot to close bracket and this will delete all the planets.
|
||||
That has gravity created and two and all these you have to remember that you in order to run them you have to use the run dp function.
|
||||
Either where you are doing it or at the upper level depending on where you want your transaction to be.
|
||||
Persistent is really nice data database library in my opinion I like it a lot it's it's easy to use easy enough to use and it's pretty straightforward like if you don't.
|
||||
If you don't know what you are doing you can often find a way of doing that you.
|
||||
I mean if you're not 100% sure of how to do some things I often find that doing the first thing that comes into mind is usually the way that.
|
||||
Persistent is doing things so it's sort of consistent it's pretty limited however like it cannot to join for example but for that it is another library called SQL it.
|
||||
That can do those and that can be used at the same time as a persistent but the problem with the SQL it or instant problem problem problem but it is that it doesn't have as nice at API as the persistent it's a pretty complex and like the.
|
||||
The power comes with the cost here the learning curve of a school at least I found it be quite a bit higher and it's not in the stack that's the package package repository of the Haskell that I'm using it's not there it's not there so in order to use that I have to download it from directly from the repository.
|
||||
Okay I hope this gave you an idea how how a powerful interesting fun the data that system in the Haskell is.
|
||||
This is start off really brief in that introduction into that.
|
||||
One thing for example we've had the storing doubles text simple simple data nothing prevents you to storing for example functions in the data date but you can say you can easily say that this for example my special data I can contain two different functions for example.
|
||||
Well I can actually explain that now that I mentioned that I can explain you can for example say that I'm going to come up with a example okay data handler equals and then simple open parent.
|
||||
Int are all to the right and more I think it's full.
|
||||
Okay pipe complex open parent int are all to the right int are all to the right int.
|
||||
Okay what did that what does this define it is a data vibe.
|
||||
This is a type handler that has two values simple.
|
||||
That is type of int booland so any function that takes a parameter int and produces booland can be placed here so you can say.
|
||||
My handler equals simple or and then then that odd is a function that tells if I'm number is a odd or you can say my handler equals complex.
|
||||
And then inside parent's plus because plus function is a function that takes two integrals and produces in there.
|
||||
It acts them up obviously so nothing nothing stops you putting functions into the inside of a data.
|
||||
Sometimes this is very useful.
|
||||
Often it's extremely useful as you can just write functions around as a data and give them to another functions and then they can use them and you can you don't have to write complete algorithms or functions in a sense that you don't have to specify all the little critical details you can give.
|
||||
Some details from the outside of that function task configuring that specific version how it handles things.
|
||||
For example search algorithms you can use in a way that you give part of the algorithm from the outside task changing how the search works.
|
||||
But that going through that would take a lot of going through what you can do with this would take long and long and long to us you can do.
|
||||
I mean I'm pretty sure that you can think by yourself where you would want to give function as a parameter to another function.
|
||||
Okay but why can't I say I hope this this clear off how the data types are defined in the hospital and how the how you can use a person to store data in the database and manipulate it.
|
||||
Okay, talk to you later. Bye.
|
||||
Thank you very much.
|
||||
Thank you.
|
||||
Reference in New Issue
Block a user