 I realized I need at least 30 minutes, and I would try to stick to the 30 minutes. But yeah, that's why it's today as a regular talk. HPEC is an alternative format for Haskell Packers. But yeah, before we start, firstly, I think a competition is a good thing. Experimenting with new ideas is always allowed. Or at least I take the freedom to experiment with whatever I want. And I think that's the basis for innovation. So, HPEC, what is it? It's an alternative format for Haskell Packers. It's based on Yaml. It generates cabal files, at least for now. Yeah, it can infer module names. I will look, see that in a minute. It removes redundancy from your cabal file, like GPC options, dependencies. Sometimes you want them into multiple sections. We have a library and a test section, and we want, by coincidence, for both sections, all warnings, stuff like that. Or a same list of, a shared list of dependencies. It provides some sugar coating. That's not crucial, but it's just nice to have, I didn't see why not. I will see that for GitHub repositories. And it, that's the mindset I developed under. It gives you 100, or me, it gives me 100% control. And that's also the main purpose of this project, that it makes my life easier. And if it happens to make somebody else's life easier, then it would be awesome. But, let me first, in this case. Okay, let's start with a short example, basically. Let's assume we have Haskell Program, a really simple one, here in main.hs, just hello world, one line. What would it take to write a cabal file for that project? We're not looking into that, but instead, we're looking into how we would use HPEC to generate the cabal file. We'll just say, we'll just say executables. Executables are mapping, because we can have multiple executables. And we'll just call it foo, for example. Yeah, that's a yaml mapping, or like JSON, basically, right? And then what would you need to specify, would say main should be main.hs, okay? And that will not work yet. Because, yeah, we also need at least one dependency, base, right? So let's put it here, and that should build, and then we could even run it and print, hello world. Okay, that's a little bit, yeah, the idea to specify as little as possible. That would be the corresponding cabal file on the right side. Yeah, we could also specify a library. I would just remove that for now, and a library, we can only have one. This one, it's not a setting. And what we would need is source directories, right? Yeah, I prepared that here, right? Let's assume we have a source directory that has source files foo and bar. And we followed a convention that in this source files foo and bar, there will be two modules foo and bar. And as we follow this convention, HPEC would just infer just from what it sees on the file system that we indeed have two modules there foo and bar and we'd expose them by default. Of course, that's not always what I want, right? Sometimes I may only want to expose one of those, for example, foo, right? And yeah, then it would just only infer the modules that are private to the package that would be bar in that case, right? Of course, if I had more modules, I would just touch bus.hs and it would also infer that one, yeah? And I may be in the situation that I say, yeah, but instead of specifying the exposed modules, I may want to specify the other modules, the private modules, right? And I could also do that, right? And then it would just assume that we want to expose foo and bar and bus would be the other modules, right? It would just always infer the other one, right? Or we could actually specify both, right? For example, let's assume for some weird reason, we're in the source repository, we have bus, but we don't care about it. We don't want any metric, we want 100% control. We just say, yeah, expose foo, bar is private and bus we just ignore. It's kind of a little bit the idea. Okay, yeah, okay, it generates cabal files. I already mentioned that, we have already seen most of it. So basically, I have a package.yaml, or if I have like a directory where I have a package.yaml and I have source directory where I have a Haskell source file that's called foo, and I have the following content. Basically, I just specify this source repository in my package.yaml, then it will infer this, or it will produce this cabal file, right? And most notably, it will infer this module here. And yeah, the same works if I have a couple of modules. It will just assume that I want to expose all of them by default. And if I don't want that default, then I have various ways to influence that. I could either specify exposed modules, right? And it would assume the other modules would be private, or I could do it the other way, I specify the other modules. We already have seen that, right? Or I could specify both lists, and then there's no magic happening, right? Then it will just infer nothing, okay? Okay, removes redundancy. Yeah, in general, we can list a couple of things in a cabal file, right? We can list GHC options, we can list dependencies. And we can do that for a library, for an executable, or for a test suite, right? HPEC allows you to specify listings globally and on a section level, in contrast to cabal. And it will then just assume that I will just merge the two lists. If you have a global one, a top level one, and a section specific one, it will just merge the two lists. For example, yeah, if you had a list of dependencies here, foo, or base, and directory, and file path, right? That would be a global one. Now, if you had another section here, for example, let's say we have tests, yeah? Tests are a mapping tool. We can have multiple test suites. Let's assume we have a test we have called mapping here. Again, for a test suite, we basically need to specify an entry point and a source repository, right? Then again, it would infer the modules that we have by coincident in that source repository, and the list of dependencies that we specified here top level would now be shared. We see that here, would be shared between the library section, right? And yeah, the test suite section, basically, yeah? And I could, of course, yeah, what is common for test suites is to have additional dependencies. For example, I could have HPEG as a dependency here, that we would just, just a little bit smaller. Yeah, then basically this top level list of dependencies would have shared between the two sections, the library and the test suite section. And here we had one additional dependency. Could, of course, be a list, like, yeah. Is there a node? Current's not, we'll see that later. Like, current state is just, I add what we need. And I'm also happy to, like, if I write C bindings, I would maybe resort to cabal or extend XHPEG, right? So far, I haven't had the use case yet, right? No, it's not. Yeah, as I say, it tries to solve the common use cases so far. I could think about it, like, adding something like that, but I'm not sure. I would, I, myself, I'm not afraid to use cabal if I do something more exotic. So, that could also be an option, just. The other thing, is there enough? I will also talk about that in a second, okay? So, basically, at the end of the talk, we'll go back there and let's talk about that quickly. Okay, I already had that, right? If you have a list of dependencies here, specified top level, it will be effective for all the sections. And the sections could also specify their own list of dependencies, same for GHC options. We only have one top level here. It would be effective for all the sections. But we could also have section-specific GHC options, right? I cannot do the same thing for source tiers. For example, here I have an executable, right? And I have a test suite. And very likely, I want to test the code that I wrote for my executable, right? The modules that I have used for my executable, right? So then I can just say globally, top level, I say source is a source repository. That will be used for the executable section and two. The executable section, in addition, has a driver directory, where it is the main driver. And the test suite will have an additional source directory test. So both of the sections would have two source directories, right? So I guess that makes sense. Yeah, sugar coding. As I mentioned before, I provide some sugar coding currently for GitHub URLs. That's of course a common thing that, but this is not. Yeah, you could do that. But I mean, HPEc currently is not tied to Git. Yeah, I mean, maybe it should. That's true. I mean, it's maybe an interesting idea, right? I'm not sure yet. I would probably think about it. That's true. I mean, it also a little bit depends if you assume that you always generate a cabal file and distribute the package with this generated cabal file. You could do a little bit more, right? If you assume that you're distributed with this HPEc or this package.yaml file and let the people generate the cabal file themselves, right? Then, yeah, it really depends what you would have in mind, yeah. But look, let's look at that. If I specify, like, as a GitHub repository, this username and repository name obviously could also be our organization here, of course. And it would just infer this source repository from that. And in addition, it would also add a home page and a bug reports URL. Just would assume that the home page is the GitHub readme and the bug reports URL would be the issue tracker on GitHub. Because I think that's the same defaults, but of course, again, I may not want that. I may want to specify my own home page. And of course, that is also possible and same for bug reports, I could just specify an email, for example. Or I may just choose that for this project, I'm not interested in bug reports. I could just null it out, basically. If I set it to null, then it would just not be generated. Again, that's the mindset. Basically, it assumes some same defaults. It does a little bit, you could call it metric, but at least it's metric that you can control and that may be a kind of metric. But at least I want, you know? Yeah, I think we already covered that. So I can either go with defaults or specify my own home page, own bug reports URL. It also does something at inference package names and it's a little bit more controversial. But if I want an executable, I just want to compile and I don't care. Then I can just, as we did in the beginning, I can just specify an executable, right? And if that, like the package.yml is in a directory called foo, then it would just assume as a package name foo, okay? It was also assumed because Kabal needs a version, it would just assume that the version is 0.0.0. Of course, I mean, of course, I can specify a different version here, right? As we would expect. Yeah, so I called this a little bit controversial. I want to minimize this controversial because, for example, if I have this under revision control and the package.yml is top level, then of course, a user could check out this repository on the arbitrary names. Yeah, so I'm not too excited about, I mean, it's really useful for like getting things quickly, but I may make this a warning or may even drop that in the future. I'm not sure yet. Yes? When you start caring about the name, then you are. Yeah, exactly, that's kind of, I mean, the only thing with this name, currently everything can be under version control, which is used to generate the Kabal file, except for the name. So this is why the name is a little bit special, yeah. Okay, yeah, things that we haven't covered so far, let me quickly, okay. Yeah, it also infers license files, it's just the thing, you know. If it happens to be that I have a file here that's called license, then it will just assume that's the license file, right? And of course, we can also specify license here. So usually we want that in combination. No, HPEC won't do that. I would also like a tool that generates more things, but HPEC doesn't do that, at least not yet. Yeah, I should add that for license, currently license doesn't support it. And yeah, license should also be, it should be possible to set it to Nile. But yeah, currently it's not. Well, you need a package name, so it has to infer one. Yeah, Nile is a treat specialist, past as Nile, or in Yama. It has to make the call. Okay, no, okay, I got that wrong. So firstly, it doesn't make sense to Nile out the package name. And yes, you can have, can you, or should I try? You can quote it, yeah, for sure, yeah, then it works. If you quote it, then it works. I guess you have to quote it, yeah, pretty sure, okay? Yeah, let's continue here. It supports most of, yeah, like the cabal fields, like category, synopsis, description. And it warrants on unknown fields. I mean, I think it's also important, like, of course, Yama is kind of free format, but that doesn't mean that we lose any sanity. Or if I say here foo equals is bar, I would just say, let's do it again, right? Ignoring unknown, it's a warning only. But yeah, it will say that. We could add a strict mode to make it an error. And yeah, we're almost through. Project status, documentation is a little bit lacking, but the readme contains links to examples. I think it's pretty straightforward. Of course, there should be a manual, but currently there's not. It's not feature complete. This means I add features as I need them. And I mentioned that before, I'm completely fine. If something's not supported, if I do something exotic, and for some reason I think it's a bad idea to add that to HPEC, then I would just use cabal for that. For example, I'm not sure if I would add flags. They're useful in some situations, but I try to go without flags. No, the only thing, it looks at a cabal file just to try to make a small diff just because I want that. If I have a project that has a cabal file at an HPEC file, then I want a minimal diff, basically. But there's no tool that would do the other way around. Of course, for my perspective, it should also be a separate tool. If I want that, like Sörnke suggested a couple of times. That would be cool, of course, to have a tool that looks at a cabal file and generates an HPEC, like a package.yaml. But I think it could be a separate tool, could be in the same project. I would love to have it, but I haven't written it. Don't include this in the diff, so don't erase this. If I regenerate the thing like that, don't take this special C option by now. No, it would always generate the whole file. Is there a way to annotate the cabal file? No, currently it's not. No, it could be. You have a much nicer integration of that. Yeah, I think I would prefer that one. Because then you still had everything in one file and you could do everything. It could be a quite useful feature. It's just single T of E. Yeah, yeah, something like that. Yeah, you could do it on a section level, yeah, that's pretty cool. You could then have a top level and on section level. Maybe that's not so bad, could be interesting to do that, yeah. Yeah, I think, yeah, it would make sense to have something in cabal. I have a way to do everything that's allowed in cabal, even if it's not supported by HPEC. But I think I like that idea, yeah. But yeah, again, for now I'm also not afraid to just use cabal if it's not supported. That's the thing you were asking before, Mikhail. Like, you were asking whether it's in first dependencies? Yeah. So currently it just infers only things that you could, except for the package name, that you could put on a revision control. That's kind of the mindset. So for that reason- The most you start programming, you know, the library pass. You don't want to repeat yourself by telling from which library it comes because they usually come from only one library. Yeah, yeah, I see this problem. I mean, I see this problem. I think there should be a better solution. I hate it to update this manually. I would love to have some tool that automates that. I just don't know yet or how exactly we'll do it. So what I could imagine, okay, and that will give me a list of packages just or- Yeah, it may be first the imports, actually, import commands in the beginning. Okay. Because it's used for jigs. Okay. Then it also infers the packages. Okay. I mean, I could imagine that it could make sense to have a tool that can put that into cabal files or package.yaml files, right? But you still want to have this on a revision control. So it needs to be in the file, I guess, in some file, at least I would assume. You're not sure? The question is, you keep configure as it's usually produced from some other file for the- Okay, so if we- So that you really want to generate each time in the first one. So the assumption would be I look at not like the package that I have on my system, but I have some global package index like from HackHatch or. So if you are building the package first time, then you want to have these versions and these packages in your cabal file. Okay. If you are building it on developer machine and you are expanding the package, changing it, then it's installed on your machine. So there are like two use cases. You can always say, first run, I just add the editor release of packages that I used previously, and I use the same list next time. But first time you start with no knowledge besides the knowledge of what it's in.UHC. That's binary packages installed. Okay. But you would still specify the dependencies. Like in gem files, you still specify the whole list of dependencies and then you just lock the versions. That's the gem. And all the transitive dependencies of course. The easiest way to make sure that you automatically do as much as possible would be not to specify them to try to infer them from environment. Okay. So you need to remember them in advisor release, which is guaranteed in general. Okay. So when you see the problem, you already fix on the same solution and unless the user tries to fix a different package. And then you just lock under version control even though you know that it's automatically generated. Yeah. I mean, I think we, at least I want to lock dependencies. And then, but then there's this other thing that I also. It remembers it. It remembers this advisory list. You just need to add this advisory list to the version control. But you can generate it also from scratch when it depends if it has not been seen well. With, with, with advisory list, you mean a list of just package without versions. Package that you use is free to run. Okay. With versions. Yeah. Okay. Always with versions. Just one lock file. Yeah. Yes. I mean, I want, I want, I want your lock files. I want better support for lock files. But yeah, HPEC doesn't do anything there yet. But let's discuss this further later maybe. Yeah. I mean, currently the, the assumptions basically it would never infer anything from your local system. Also not from the internet. For that reason, currently the mindset is there would not be a config file. That's, you could of course have a config file where you specify the author and stuff. You know, because that's almost me. But currently it says, yeah, everything that it uses to generate the cabal file would be in the repository so that everybody can go there and regenerate it, right? On any system. Yeah. And I use it every day. I would not want to, to, to be without it. Even so, it seems like a small thing, right? It's not a big thing. It's also not, you know, you can't write a paper about it. But I still think it reduces a lot of repetitive tasks for me at least. And yeah, we use it for all new projects at Zalora. Okay, so this is, this is our slide. So we could still. So there is a casual carbon, which actually concentrates more on tricky things like read polling, making sure that the documentation always follows the compiled code, NILs, which mostly focuses on building and uploading it. And the only part that NIL is called NIL, it's pretty easy to find. Okay. And there is also stack, but it's just a, yeah, yeah. Yeah, I saw that, yeah. Okay, that would be from my side. Are there any questions? I have a comment. Yeah? Of course, this situation is a little bit specific to Hspec, because Hspec, as it does automatic test discovery, it will just always generate a main driver that includes the test files that are there. So this actually did good case, in that case they are good, not sure. But then if some test file is missing, then it would just, because it's not specified in the cabal file, then it would just not be executed. If you, with an executable or a test suite section, if you don't have this automatic discovery feature and forget it, then cabal1 complain, you can just package it, upload it to Hack Edge. And then on install time, it will just fail because the module is actually missing, yeah, so. Yeah, yeah, that's a common thing, you're right. Yeah, that's, I think we see it a lot in Travis files, right? That we do a cabal estest and then do a cabal install on that. Generate a tab all for that reason, yeah, makes sense. But if you have a tool that just, at least for me, if I have a tool that just infers it, then the better, right? It won't even fail, because even if I have a failing build on Travis, it takes my time, kind of. Okay, I think we have four talks today. I think that's about 30 minutes. So maybe we should just stop here and continue discussing later.