 Hi, yeah, we're here trying to program a bit of web back-end in Haskell so Just let me introduce myself. I'm Alejandro. I work the university as a PhD student. I Use Haskell normally not that much web development, but I do sometimes I also wrote a book about Haskell We actually can read about all of this stuff if you want to read more So First just a few things my idea would be to to to run This workshop in four blocks so its block will have a bit of me telling you something and Then a bit of you reading and doing so first of all we'll talk about routing and how to create some HTML then about Database access then form some validation and finally how you can Deploy and add some middle word to your web and in the middle I would like to to leave ten minutes so we can just go to the bathroom have something or whatever and and also to to Have some question and answer part so in the in the practical part feel free to to ask some questions and I think what is what works quite good is we Keep track of the question that are interested and then we all speak about how this can be solved So the exercises are are indeed github For every exercise there is a template for the solution so you don't have to keep to to to lose time Trying to create a cabal project and writing like a lot of code and you go directly to what we are going to learn today you May not be able to finish everything here. Actually. I think if you finish everything in the time Then you shouldn't have come at the at all And I actually would suggest to work in pairs because I When when when I've been learning Haskell I noticed that people usually learn there from many different Perspectives and sometimes it's nice to see how all the people code to Think about how you code yourself So that's my suggestion, but of course feel free to work alone if you want so so first of all as an introduction sometimes if when you try to to approach something like web development in a in in a new language The landscape just looks so big so In Haskell you have a lot of library. You have like web framework You have have stuck snap you said and people saying one's better one It's the other one is better for some other thing You have a lot of ways to access database and these things Usually look very different from each other. You have many different ways to do some plating and and well this Happens in every language. So yes, don't don't feel scared about this For today the menu is going to be to talk about the Spock framework and to talk about the persistent library for database access And then we are going to talk about blaze and sex sphere for templating so what You may wondering is is I'm actually hiding you something from telling you these things and instead of the other things Well, I don't think so because the way these libraries are are developed are very modular So actually persistent, which is a database library. We are going to talk about Was part of persistent and it it was part of Jesus. Sorry, and it became its own living organism blaze templating was done before any of the other frame were actually existed so and you can miss all of this How you do this is well, you have a lot of strong conference via typing So so you can match them and ensure that everything works together well because of these types and and also most of the of the things that this Libraries are structured most of the concept are just general concepts in Haskell language like Monads like functures So so you should be able to take all the things that you learned today and go to a snap or use it and apply most of them But of course, this is not a definite choice. Plus if you are going to use Haskell to create your super nice web application in production Just don't use what I told you before reading what actually may be better for your specific case In any way what I chose I chose it because of simplicity So all the libraries we are going to look today are very simple But they are examples of how Haskell approaches this whole area of web development in a Strongly different way that you could do this with Python with Scala with any other language So with a lot of typing with a lot of interface based on functor applicative Monads and all of that So just before I start really When you are going to run the exercises, it's just going to be a cabal project cabal is the tool to build and distribute Haskell code is a bit of And and you get an MPM all together and mix in sometimes not very nice way it builds a project it unloads all the dependencies and Sometimes you have to spend a day trying to make it work again, but if you follow the instruction to to Prepare for the worship you could have installed all the dependencies So you that there shouldn't be any problem today in this in any way. Just tell me if you have this However This is not the best way to work if you are actually running a Haskell project because The libraries are not going to be sandbox. So that that means that they are going to be shared across all the projects We are working today, which is nice because we don't have that much time to download the dependencies over and over again But if you're working in a project, I encourage you to use the sandboxes in cabal. So now that You know all the preliminaries Let's Move into this. So Basically the talks the talk is The theoretical parts go is me showing some small pieces of code and trying to explain how this works. I Would suggest not not you're not trying to copy in this in your in your machine In the in the github repository. You have all the code that actually runs so you can copy and look from from there So, okay, the first thing of course we need to do is to create a hello world and Creating a hello goal is just too simple for us, which are developers which we already know So we will we will start by saying hello and your name afterwards and So this is how the code looks so right now it's just like a bunch of different things so You you you can See two different three different parts. So you have the type signature of the main thing, which is just common Haskell thing and then your main has a first line with just setups running your your application on a web server which is integrated in this a spoke framework so you basically you say round your spoke application on port 8080 and then you just have a spokety, which you don't really need to care too much right now What what does it mean and then what you get is a list of? Description of your roots so here what you what you say is okay every time you You have something which is started with hello and Some name here, please execute this part of code and And and what you should do is just return the text hello and the name So this this is should be very basic just Try to create a root and return some text so Each of these parts is what we call a handler and if you are used to this Kind of Sinatra a Scalatra flask type of web frameworks. You will notice that this look very very similar First you have a verb, which is what kind of request You are going to get so you can get you can use get you can use pause to delete all the all the common HTTP verbs Then you have a root and then you have the action to perform or something matches on this route and And and if you notice the root is not like a string is actually done of different parts and Each of these parts can be three things so you can have just a literal string Which is going to be matched as it is in this case. Hello you can have Slash-slash to make a separator and you can also have variables and these variables are what it's going to be captured and be Given to you as parameters, so if you have here hello young then your name parameter is going to take young Which is interesting here is that actually these roots are type safe So if I declare this thing so I have allow and then a variable and I say okay Please ensure that H is an integer So when I try to match something like allow feature this doesn't match the route So this is not going to be executed But if I have allowed three days will match the route and I actually it will tell you that you are not allowed So this is it This is I think this is nice because this is showing you how you can use types to do something more than just checking your invariant This is actually Giving you a contract that your roots should also verify So Right now the action has just been text But you have you can have a lot of action being performant and the best thing is you Just query the documentation for all the things that you can do what it's important Is that all this action for a Mona that means that you can just basically say one after the other and this will be the Result of all your all your action So for example here you can set a cookie and then return text, but you can also redirect you can Set the contact types at any kind of header. So you do this this way So if you would like to say hello, but now instead of saying just the text returning HTML You could of course do this you could create your HTML This fancy is more than smaller than greater than is just the concatenation Operator that works for this kind of string which are not strings. That's another different type, but Okay, say you could try to do this But this of course is is very bad. It's hard to maintain What happens if you? Forgot to close at h1. What about injection attacks? Ah? You shouldn't do that. We all know that this is this is wrong You should be all screaming and going out of the room because I just show you that on the screen so Let's look at how you return HTML and force and force in this world for madness so You have as I told you have many of these libraries You have blaze which is based of kind of showing HTML as a monad and and this Haskell code imitates the HTML structure so you will see now an example and and Basically, it's like you write your HTML, but it's it looks like Haskell You also have sex beer which is actually the idea that you can write HTML and Then be treated by the compiler before by using template Haskell to generate Your type-safe code and you have also many other kind of template you have haze which is which looks more like php or Jsp kind of templates where you have places which are are change So if we are going to write our hello hello with blaze, that's how it looks like so you can see that that the The HTML part which is everything but the first two lines just follows the the structure of your HTML So you have HTML body h1 and then inside when you want to have more than one thing You use do because this this is Also a monad so you can sequence different things and you have this exclamation mark to attach attributes to your to your HTML so This this this is well first of all this is Haskell code. So this is all type check. So for example if a Style takes a string, but if you have something like with which takes a Number of pixels then you will have an integer there. So somebody took care to make everything type-safe You since this is also a Haskell code. You could use your your Maps your foals whatever to generate this code, which is also nice and And also the text here you can see we say text name takes care of the injection attack So it ensures that whatever the the user Fits you in it will be given as a real HTML and something which which they can give you a script if you were more into into writing HTML instead you can use sex pure which is a app a whole range of of Yeah, they are called quasi-quoatures, but this is not the fancy name of things which Translate from things that look like other languages into Haskell in this case This translates into things that looks into HTML into the actual previous code So writing this is exactly the same thing that is I wrote the previous code If you look there are these fancy things here this And this is Hamlet, which is what is called the quasi-quoter. It basically tells the compiler, please Instead of you taking care of this Please call the sHamlet function before which is in some library and then replace what it gives you in my code it's sort of a Macro system some kind of thing but not really a macro is more like a in list we have this read I Don't know that I don't remember the name right now Well, anyway, you have here some kind of create bindings and then This this is nice. We can create things that look like HTML, but then we will need to convert it to a String to be actually return. So you have this you can look that there is a render HTML which Moves from the HTML to the actual String but this a string is not actually of The string type is of another type called text, which is more performant if you are going to make string manipulation so Actually the full story that actually you don't have a text type Is that you have a lazy text type and a strict text type because sometimes you would like to use one or the other and unfortunately blaze and Spock developers think differently about what they should be using So you have to convert from the lazy type which is given by by a blaze or hamlet to the strict So that's why you have to strict and then you basically have the HTML, which is what Spock see if you can return HTML So Yeah, so far so good. So now it's time for fun. Yes. Take some exercises. I have two of them If I recommend if you are a beginner in Haskell you use the first one which tells you how to return Jason instead of HTML It shouldn't change that mud but introduce a very useful library called ason and It also has some exercise on basics routine if you are an advanced has killer I suggest you to go to the second exercise, which is how you could Have an application a state by using another library, which is called STM. Just about software transactional memory so And don't be shy as question we will write them the interesting one and we'll share after the break Yes, if you have some question in the meantime, I'll just raise your hand. I will be going around So yeah, have fun. I mean Five ten minutes will go back and and speak about databases Yeah As the e1 so the p1 so the ones that the net the ones named p are about the What I've shown you here So if you need to copy code or see a full example, you can use it there and e1 are the exercises I think or are no they are the other way around Yeah, the p1 are the ones here here is the the URL if you How many people are downloading cabal libraries? Okay, let while you are downloading let's move on and then you can have more time Later to do this. I think that's gonna be a bit more useful than Okay so that a basis because Yeah, the data. It's important. Yeah, just running our Haskell application. It's going to make us very happy, but not our customers so we want to save the data and There Two main approaches here as in many languages you have all these libraries with just target a particular database you have for post SQL for my SQL for SQLite for Mongo, but you have also some libraries which Provide a common access layer so I Really think that there are many many cool stuff in the first part about relational algebra would you actually think in a more Yeah relational algebra thinking of what your queries are, but I think the more productive Library to do database in in Haskell is persisting which is sort of a functional or M which is an object relational mapper, so it's going to be like a Record an error M record relational mapper something like this. Anyway Basically what what do you do if you want to use this library is first you This define an a schema So do you tell the library how your data should look like and it's look like this and if you notice We are using again a course a quarter So we this is not the the part in the between the the bars is not Haskell code. It's just a Small language which allows you to define what is tons and tons of Haskell code actually I can After I can I can show you how much code this generates, but basically here you are saying okay have two to entities user and task and you have And a user has a last name and first name and a task has a title and a user so Just spoiler our exes are going to to be about somebody creating a web application about users and tasks And you have other stuff we will we will go later so So basically what this is generating it's in your head should be something like Something like I define my data User user First name is a string and your last name So this this this define this Haskell code plus a lot of more thing. Yeah This is So if you look at the first exercise, there is how you can derive your Jason data type to convert from a record to Jason automatically. So this is basically calling the thing Front so you don't have to write it. So it saves you like ten characters, but Yeah, and and the unique we are going to speak about it later. So basically this is this is doing this But it also generates a lot of other stuff for example at honor another data type which is called user key Which is a data type that we are going to use to to to Speak about identifiers only for this kind of entities It's also generates a data type entity field of user which Tells which are all the fields in this entity and we will see that this is useful later When you when you want to refer to a field in an entity in a query like tell me things that has us first name this and it also generates Uniqueness and data type that represent uniqueness constraint. So in this schema what unique name with this capital you is telling is Ensure that Every record has a unique combination first name and last name So this is how how you can you can do this also in most of SQL databases. So But it Generate So so if This code this code I'm showing you here It's not going to generate code to generate the schema and you can have something which is called like me great Which also generates a code to create the schema in a database But this is only because if you want to have everything well type and to ensure that everything you do is well type You have to give all this information up front Yeah, and also yeah instances for DB and Jason serialization. So this is taking care and it does the same for task So the first thing you will notice if if you open the project With this is that now we have a lot more Code instead of our our run spoke which was if you look that the the white part It's what we had before and now we have a lot of things around it So there are some parts which Yeah, well, there are three different parts the the the orange one is something that unfortunately we have to we have to do is just Set up some login because persistent forces us to do so. So here. We are just saying please don't log anything But this is just Something I don't want you to take care of this So you if you are doing logging you should look about how to do logging properly with this But here I just not doing logging, but we need it to compile and then We use here this sqlite with sqlite pool so this is creating a pool of ten connection to the example dot DB database and Every time we we run We want to run a query or to do something on the database We are going to use this pool to get connection and this all takes care of the pooling and Ensuring that everything's get teared down when it should and and all of that And and then if you want to run a transaction what you do is you run You use run sql persist and pull and you give the pool and the thing you want to run Which is this f and this performs this using this pool of connection. I don't know that what this is Completely clear. This is a lot of code. Basically the important part is that we are using here a pool of connection We have to set up with the with the green part and when we want to use it within we cannot just call f We want to run f using this pool. So we use run sql persist and pull with this pool You will notice anyway that there is something going on there, which is this lift I owe that I have here and And and what's it all about so so database access is not really something that is pure does some input output But that means that when we run some things on your on our database We have to run it in the IOM on it, which is the way in win in which Haskell separates the impure codes from the pure code but So so we would like to do this but unfortunately we are inside other Monad, which is the Monad using by a Spock So a Spock have its own Monad with takes care of a lot of stuff But there is a type class called Monad I O which Helps you to move from any kind of I O thing that you want to do into a larger Monad in this case a Spock a Spock T is an instance of this Monad I O class So every time we have an I O and we want to run I O inside our our web application We need to run lift I O to move from our I O a to a Spock T of a and this is what the lift I O So did this this is usually very useful if you are doing this kind of Real-world Haskell things you do define something which is a Monad I O and and then you can run any I O inside so This breaks a bit all this purity that you have here But if you if you are doing something the database access you have you really need to do this Okay, so Yeah, let me go quickly through this so do you use persistent you have the normal thing So you can insert things on the database and we are using here insert unique and you can see that we just give an An an object which is a value of this data type So this is the data type that it was generated and we can use it at any other Haskell data type and we just call insert unique and this takes care of Inserting the thing in the database and check that the uniqueness constraints are satisfied and it returns you Either nothing which means I couldn't insert it or maybe with the identifier You also have insert which is a different alternative with doesn't check the uniqueness constraint So it depends on your on your own On your own problem domain whether you want to enforce the constraints when you insert or not you can also query by identifier that means Something that I forgot to explain you just every any kind of these types come with always with an extra Field which is the ID and this is always taken care by by persistent so you never see this so You don't see here an ID field It's only in the database But when you want to query things you have to know that this ID exists and this ID is not only Something which is an integer is Something of your a specific user key ties So if you have a task then you have a specific task key type and this Ensure that you are not using an identifier in a wrong place. So if you want So so No, no, so what there is is a default for each kind of database. So every every Every connector to a database defines my by my default my ID is gonna be I know that for SQL is an integer for MongoDB is one of these you IDs But but you can define it yourself No, yes. Yes, you can you can of course overwrite all of this given but but the the syntax is not It's this kind of sin that was discouraged you to do this. So But you can do this Okay So as I said keys are strongly typed So you cannot really mistake a task key for a user key But it also means that when I want to query something and they give me just the integer So this user ID is going to be inferred to be an an integer. I have to create a user key out of this out of these Integral and I do this while in this case. I'm using SQL. So I use SQL backend key Which well, it's just a type synonym for integer in this case and you can also see here That you you can use spark to to return a 404 error if you want by set status Yeah, so this this code is wrong this so I should in the real code I have The get from the DB is qualified. So as DB dot get it it will complain if you try to run this as it is here Yeah, thanks You can query by identifier. You can also query by By data and you do this using select list and you have also select keys if you only want the keys or select so if you want instead of a list of source, which is Son of a more performant data type if you are going to do a streaming computation But basically in this case you you can see that we are using a new a new Kind of values, which is this user first name and user last names are constructed at where we're not mentioned either in the In the definition of the schema, but are things that are generated by persistent to refer to each of the fields So when I use user first name, that's the first name Field of the user of the user entity. So this again strongly type And you have a lot of different kind of condition you have equal you have less than you have all kind of SQL thing In this case a bit weird that and is represented by list concatenation and or has a special a special Operator or but that's that's how it is And if you want to do more things like please Order this or limit to a number of things there are many many things you can look at the documentation So just I don't want to be exhaustive here. So time for fun again So there are two exercises more One is about working with persistent and learning how to update and delete which is most of the time It's just instead of get you use delete or or or update and I also have another exercise Which goes one step farther than this persistent library, which is the skeletal library Which Exists for for because of the fact that persistent Targets a lot of different kind of databases not only sequel but also no sequel databases So that means that its query language is very limited to the intersection of all of this but escalate allows you to create code that only works with SQL but is More performant than SQL for example, if you want to do a join Persistent doesn't have a join operation. You really have to go and make a You have to round trip you have to get your data and then for each of this go around but this allows you to have joined so And also have a sin that which is more similar to SQL So I encourage you to look at this if you want to know more. So again Don't be shy and ask question and Yeah, after after this like In in 10 15 minutes there will be a break and I would like to use this to to have a question and answer part so Like in 10 minutes So have fun. Yeah Yeah, you cannot you you you you can do this so it's just a data type it's really it's so it follows this kind of of Or and would you really have to be very explicit on when you save things? And there is it's not like I think active record in Ruby is kind of this thing where you change things And you don't have to name and but here you have to do everything very very explicitly Yeah, you can do all of this so you can also create an update which only says Update this record and it doesn't give you back So you don't have to do get the record update and put it back So you can do this but but if you don't save it, then it's just not safe on the database so let's let's go back into trying to Explain some small thing first of all I promise you that I would show you what this schema is generating So this is the documentation for the the module for the They be module in the in this exercise I just did this running cabal haddock Which is the tool to create the documentation and you can see that it generates the type as I said So it's like user with first name and last name But then it generates how to show it how to convert it to Jason and then it also Created some other data types which are just local to this definition of Of users so key for the user is actually a new data type also for the field So you can see that all of this was generated from you and user ID is key of user and The same for tasks. So this actually generated a lot of code for you so Yeah Let's go back so then the next thing is now you wrote some code But you didn't actually check that anything was correct. So what if they gave you? user which Has an ID with doesn't exist or something like that you you will get an error from the database But you would like to validate this before So so yeah, what's the user doesn't exist what the task title is empty? So we need validation So the first thing you would do is okay. Why don't we do it by hand? Just create a validate function with gets a thing and returns a Boolean tell me just or no And then if I call this validation and then if it works then I do something and and if doesn't then I just return a different thing Instead you can think oh what instead of return just a Boolean I actually return one of these maybe types. So I return nothing which is Well, this is hasn't been validated or I just return the same element in a just constructor so So you can do this like this and it's makes I Would say that the same sense But actually doing the thing with the with maybe is actually a great idea because maybe it's a very composable thing It's a function and a picket if an alternative a monad a monad plus is all sort of things that we all like to to say at least I like to say picket if an alternative So So we are not going to look at maybe as a monad today. We are going to look it as an applicative So if you follow the news in GHC Applicative has recently become a superclass of monad which basically means that every monad is now an applicative But not every applicative is a monad. So this is just like a more general abstraction that moment has And what it gives you is this set of operation on a data type So you can return you have pure which just has a value and wrap it somehow into into me into discuss maybe You have you can map a function. So this is like f-map. This is like your function mapping But you also have this composition that if you look like there is an extra maybe there And this is going that's where the powers come from because That allows you to to sequence a set of Validations and if one of it fails and the whole thing fail So the rule for this may be applicative is if something is nothing Nothing is what you will be given out So how you use this applicative pattern when you want to use validation So imagine you have some basic data uses you have title, which is a maybe string You have a user which is a maybe user you got from the database because maybe the user does not exist And you have this non-empty thing which checks whether a string is not empty and just to make the code a bit smaller I I just wrap it from maybe string to maybe string. So what you would do is, okay How do I create a task a task has a user and? A title So if I want to check that the user is correct the title is correct And if everything is correct, then I want to apply the task constructor. You always use This kind of thing you use the dollar at the beginning And you use the the star And you can have more than one star. So this this actually Can be any number of arguments. So this is sort of like you have function application But you have this extra effect from the maybe Which in this case is if something is nothing does please give me nothing out and there are many many applicatives so every moment is an applicative but but So you have a lot of things from there, but there are many other things which are applicative And in the case of the validation this works really really neatly Basically, basically why you can so so you have this problem for many other data types like either So when you have this kind of error like thing if you stop on the first error This is gonna be a moment But if you want to to group have as much error as possible usually it doesn't and why is because in a moment You can have something depending on the previous results. So one thing you cannot do with an applicative is This checking to depend on this checking So this the types doesn't allow you to do this, but you can do this with a moment You could have like let Sorry, like do check this and then check this depending on the value of non-NT So the fact that you can do this Forces you to stop on the first error because then what would you do if the other thing has an error? So this makes a moment But if you want to have everything then it doesn't form a moment anymore. So this is more or less the other idea So usually all of them are sort of This kind of thing where you have several things running in parallel. So there is there is Other so there are some examples where there are things which are not actually Mone are only applicative and a monad and they differ and how you do this So there is a library called hacksal which has this Sort of problem, but then they they wrap it in such a way that you cannot observe the differences So this sort of it's applicative and not a monad, but by abstracting what you cannot do then they sort of Make it right again The other thing you need to know if you want to do use it like in a web framework is how you get Information from the parameter of a posquery. So this is like let's move on to a completely different thing But you need to know this before I can show you the rest of examples So the interface for a spark is just to use param as and as in the other case it takes care of of Type inference, so it is param usually it's only returns Maybe so it returns a maybe of something and this infers the type of the maybe to return base one this case how you use it So if you look there Here I'm using param first name and last name to get my first and last name if they are not there then Then nothing will be given and then I'm using the the maybe to to ensure that user is Nothing, so if I get nothing that's before because there is some wrong user data either the first name or the last name are empty And if everything is okay, then I can I use the rest Okay, so maybe it's not the best and the solution is something similar to validation Why it's not the best first there are no error messages so that you fail But okay, that's really not helpful for the user to to return us better results Then there is also the problem so so you define how your validation is done But you don't define how you wonder this this problems to be displayed how to connect your maybe with your parameters So you we had to do this ourselves by hand. So this is not nice So this problem is solved by a library called digestive functors Which defines a bunch of of data types? called forms and views Which allows you to to save all this information so a form will It's like a maybe where you have extra information about which parameter should hold each information And what's the error? What's the error message to give it if this if there is a problem There is they also have views which allow you to to to display information. So to to move from a Form at the definition of a form you give it some data and then you get a view like is this correct Or do you have some errors on which are the errors and then there is a? library called a spoke digestive which connects directly from a from a spoke Request to one of these digestive functor definitions, so you usually have so you can reuse this this this thing for many other libraries you have like a Spock for many like for many libraries and also if you are using G So they have their all implementation of forms, but the a form is like this Dejective functor you have also m form which is a form which is monadic Which has some of the problems we were mentioning before but you do need it sometimes So how you define a form? So if you look we have the same thing as before we have the the dollar thingy and the star thingy And we have the checks, but now we have some extra information So instead of just calling the not empty I'm calling check which has a Abulian predicate and then if this fails this the error message to so and you also have this Dot colon to refer to identifiers, so basically what this is saying is sort of what we were doing before But taking care of all the parameters and everything But now it's doing everything in one go so it it looks at the first name and then it checks it's not empty with not rule and then if If it is this the error to show and you have also this check and with a special kind of checking Which allows you to perform monadic action so you don't so for example if you want to Look in the database like we are doing here. Then it's this is not a pure function. This is a monadic function So you you can also use it Here with that yes, so when you have a form you use this following this this sort of life cycle And I'm using Haskell and life cycle in the same phrase, which is not usually done Anyway, so you have your your form and usually the first time your user comes to you It makes you a get request for your for your Thing so you take this form and then you run it through get form and it returns a view Which is a view of an empty form So how how is the data of this form if there is no no information given? So and then you can you can convert it to html or Jason or whatever When it goes back again, then it won't be a get request what the post request with some parameters So instead of get form you call it with run form and if this is okay Then you get your shiny shiny just thing or well in this case won't be a just will be like View of this thing and it's okay So you just do whatever you want to do and if you have errors you get a view again So this view is the information of the form plus all the error So that's the information that you should display to the user back So this doesn't tell you how to display in the sense that which is the html you have to do it yourself But it tells you which is the information that you should display to the user Given the information of the checking that you've you've said So Here is the same life cycle, but here but now with our example of a new user So if you get a new user then I'm going to define what I define my user form So I get I use get form and get my V which is the view and Now I I want to convert this view to html And I will I will show you function user view later to convert from a view to html And then the rest is just what we were doing before so this view is going to be a form element in html We wrap it into a body and html and when we turn it with with a spoke if we have the the post then what we get Here is Is a view and then the information from the type and this type this new you is gonna be just or nothing like I said we were using maybe and if it's just we do what we were doing before and if it's nothing Then we can actually reuse the same thing if we write it in the way that if there is ever show me the errors So we can actually we could have actually Make this one one function So this is how it works you either use get form or run form depending on the on the point you are with the data and Now you have to move from your view to your html and how you do this well You basically can do it by hand, but there is a nice library called digestive blaze which allows you to perform this Easily so you have like a special things like a rural Error list or impute input text with take care of generating both the code for the So they look at the information in your in your form definition and it tell and it shows okay What should be the type of these how should I convert it so if I use write input text But this is a number then it takes care of some things on there So it's just a nicer wrapper around generate in your html. So this is not really very important, but You to know that this kind of Thing library success to make life easier So time for more fun. So but that's today Yeah, just just one time because we are spending a lot of time or downloading cabal things So we only have time for one exercise today So that's just a form for creating tasks given a user identifier and we have an extra exercise Which is by choosing an user from a list so that means that you have to Generate your information about all the possible users beforehand before showing the form and extra you will you can see in these exercises that Defining things in this way. It's does not only resemble more what you think about is also you can reuse this for Not only for for post or get in a spoke You can use it if you are working with JSON data You can reuse the same form definition and then the last name and first name will be your your The the keys in your JSON object and if you are there are many of these things So if you are using web so good then well, I suppose that these also uses JSON But there are many of these things to to connect forms to many kind of input data and output data So the thing is Spark Scotty which is another web framework you said all built on top of a common API Which is called the web application interface or why? So that means that the that so this this gives you two benefits first of all The same application can run in different contexts because this application is not really Dependent on the web server. You are running it doesn't even have to be a web server. So there there are things like Like a thing called way handler webkit which sort of wraps your application and shows us as a Said JTK application you see in JTK webkit and you can also so usually you when you Run when you are running it now, you're running it through a standalone website, which is called warp but if you were if you would like to have this like in an Apache environment, then you would use another handler which make it like into a fast CGI Interface so this is this is nice because you can run your same application in different contexts So how does this this application usually look like so you have this web server here and then you have your application Which uses whatever framework you like and there is just this layer in blue Which is the the application interface. That's how you communicate But actually why application are really really really really simple So they are almost like this, so I'm not telling you the truth. That's not exactly the type But it's basically you have a request you tell me a request and then I give you a response And then I'm allowed to do some IO Things because people thought that it's quite common to do IO inside a web server So it's this this is very composable actually because if you if you think if you have something which changes a bit The request is just like a function from request to request Or if it you want to change the response a bit to change some headers Then it's just like something from response to response. So in case you were wondering the actual data type looks more like Request To request to IO response To IO response I'm a bit more complicated You will like this because then you can you can do some things a bit faster So what it means is that actually in in this thing you can put something in between and this something in between is gonna be Very simple. It's gonna change something on the wrist on the request That it's going to be passed or whatever the response is it's gonna is going to change something and this is middle where and this is common throughout all these Things that work in in way. I servers. So you have something like Middleware static which is used to serve static file. So You've been running something we generate HTML But sometimes that you would like just to to generate to have some HTML pre-process and this to be to be shown to the user You have also middleware pre-processor which runs a command before serving. So this is helpful if you So you julep Haskell so you are going to write your front end application also using gcgs or pure script But you have to compile this thing before showing them to the user So this middleware takes care of this or that you can use it for any kind of pre-processor And you have also way extra which has like tons and tons of this middleware which wraps something and adds like compression basic authentication through HTTP and and a lot of different stuff. So you can look at you can look at all of this middleware and and but really that the Yeah, the takeaway here is that since our application have does that simple simple type It's very easy to think how our middleware will work. So that that's a takeaway from here So if you want to use the middleware in Spock instead of in any way Application there is a specific call to be made which is middleware and this sort of says okay from from now on Whatever my Spock application. It's now. It's going to be robbed by this middleware time telling you so it looks a bit strange Because it sort of looks like monadic like you are saying this the middleware and that's together But you should think like the middleware is configuring the server to have this middleware around and in this case we are configuring Using the the middleware static Package So if we have something we will we'll first try to look it on the static Directory so this what The policy which is try to look in something which you had base before so static slash whatever you told me Try to look it and if it doesn't then try with the rest so This is just in one line. You can add this static files here and Then so we we've been building all this shiny new application Which is going to rule the world and we want to deploy it So our application finally leaves the nest and I just want to show again this picture Which I really love that you have seen So Basically that's what all so I'm not going to tell you anything about deployment apart from the fact that it's quite easy to deploy And things like Heroku, so it's it's quite easy and one of the exercises about how you can do this So there there is basically you have your cabal project and from this you can get all the information and then You just call it to deploy and it runs and I can and I can I Can show you that I've done this myself and it actually runs if you in case you do think that that cannot be true So Yeah, so Okay, so then thanks for for listening and you can you can find me there and going around So thanks