Simple Haskell Handbook with Marco Sampellegrini
Special guest Marco Sampellegrini talks with us about his recent book, The Simple Haskell Handbook. The book describes a project driven approach to Haskell development, using a continuous integration server as a motivating example.
Episode 47 was published on 2021-06-01.
>> Hello and welcome to the Haskell Weekly podcast. This is a show about Haskell, a purely functional programming language. I'm your host Taylor Fausak. I'm the Director of Software Engineering at ACI Learning. And I'm very excited because today I have a special guest with me, Marco Sampellegrini, the author of The Simple Haskell Handbook. Thanks for joining me today, Marco.
>> Hey, thanks for having me.
>> And we were talking before about challenging last names. My last name is challenging and yours is too, so I want to get it right. Could you say your own name, so that way we have it?
>> Sure, so my full name is Marco Sampellegrini.
>> Alright. I'm not going to try it because I know I can't do it, but I wanted to get it on the record. So, Marco, could you tell us about yourself? What do you do?
>> Yeah, so I recently started consulting. So, sometimes that involves Haskell. Sometimes it doesn't. Previous to that, I worked with a variety of companies in a variety of technologies and programming languages. And I recently published my first book, The Simple Haskell Handbook, which is available on Leanpub. And it's currently in the number one spot in the top books section.
>> Yeah, thank you. I'm really proud of that and really grateful. And I would like to thank everyone who's purchased the book. I'm really grateful.
>> Yeah. And we will put a link to Leanpub in the notes for this episode. So if anyone listening wants to go grab it, it'll be right there. So, yeah. Again, congratulations on being on the number one spot. I think that really speaks to the desire of the community to have this type of resource. And could you tell us like, what is this book trying to do?
>> So this is a book I kind of wish I had when I was getting into Haskell. So I really missed up practical resource where I could, you know, get to understand what the workflow was like in developing a Haskell application and what the mindset. Like what the process would look like, if you will. And initially my idea wasn't to create a book, it was to create that sort of a video course or some sort of screencast. But I quickly realized that that would have taken me like 10 years to complete. in order to get like three minutes of decent video material, I had to spend three hours between recording and editing. So that was completely out of the --- out of the table for me. And the way it shifted to becoming a book is that I --- at some point I thought: well, if I have a script that I can follow when I record my videos, maybe the process will shorten a bit. And so I started writing the script in a very conversational style. And I had all of the, you know, code snippets in between so that I can type them out when --- while recording. And it turns out that doesn't really improve the situation when recording. But I kind of enjoyed writing that. And I realized that if I formatted it properly and, you know, packaged it up nicely, maybe it could become a self-standing product that could be as useful as the original video idea.
>> It's interesting, you don't often hear about writing a book being like the easy way out. Usually a bit of a struggle. But yeah compared to video, it definitely seems easier.
>> It has been a struggle. Don't get me wrong. It took me a few months to write. But I had, you know, these urge to share with the community something that could be helpful to intermediate Haskellers. And I know --- and I knew that, you know, there was this need because I've gone through the process of learning Haskell myself. And I kept wishing something like this existed. So hopefully, you know, it's doing its job.
>> So you mentioned that you've worked with some other languages, both in the past and still currently. When did you start learning Haskell, and what kind of drew you to it in the first place?
>> Yeah, I have heard that a lot about Elm being kind of the gateway drug into Haskell, or Haskell type languages. And we found that to be true here where I work as well because our front end team works in Elm. And that was actually the first thing that got us working with Haskell. Cause we saw that and were like, Hey, that's actually pretty nice. We want some of that on the backend.
>> Yeah, I agree. Like, I really don't understand when people complain about Elm. Like you hear things like, oh, it sucks. It doesn't even have type classes. Oh my God. But yeah, that doesn't make any sense to me because, you know, that's why by design. It doesn't have type classes. And it's great that it doesn't, because it makes it so much more approachable.
>> To people that are just getting started.
>> Absolutely. Well we don't need to re-litigate all the complaints against Elm on this podcast. We'd be here all day. But I agree with you. I think Elm is a great language. So turning our attention back to the book. It's an intermediate kind of exploration of a project in Haskell but what is it building? What's the book about?
>> Yeah, so it was very important to me to find a project that was kind of real world. Like I think there's very little point in building a to-do list or a blog or a clone of some popular app. Mostly because it would do a disservice to Haskell. I think if you would build the same thing in a popular framework, like Laravel or Rails, you'd get a much better experience, unfortunately. Because there is so little business logic involved and so, other frameworks outshine Haskell, unfortunately. So I wanted to find something that had a somewhat involved domain. And something that would allow me to show other features of the Haskell runtime, like STM or, you know, stuff that as developers, we do all day long. So making HTTP requests and that kind of stuff. And, you know, I'm a big fan of Drone, which is a popular continuous integration server. I've used it in production. And I always admired its simplicity. It's basically a glorified shell script that invokes Docker containers. And so --- and so I thought, wouldn't it be nice to have a simplified clone of Drone written in Haskell. Like, that would allow me to showcase all of the features that I cared about. It would allow me to have multiple nodes running at the same time. And, you know, it would have a quite, well not complex, but like an interesting architecture. And yeah, so that's where Quad came out.
>> That's a good name. So yeah, in this book, building Quad, a continuous integration server, And I like what you touched on there of, if we were looking at a simpler project, like, a to-do list, most of the stuff would just be boiler plate. And you don't really get to show off Haskell strengths. So you mentioned STM. I think another thing that Haskell really excels at is async stuff. So running multiple things at the same time. And I think, Quad ends up with a bit of like a job queue going on as well. So yeah I just want to say, like, I really liked this approach of the book and the problem that you're solving in it. I think it's a good way to show off Haskell's strengths.
>> Thank you. Yeah. And yeah, async is another thing that. It's so difficult to get right in other platforms, in other languages. You know, working with Node, dealing with concurrency is an absolute nightmare. And it's so easy in Haskell to spawn green threads. As you say, there is a fairly primitive job queue in Quad. I say primitive because it processes only --- like agents can only process one job at a time. But that's mostly because I wanted to keep the number of lines of code down, rather than any deficiency in the runtime, which has first-class support for concurrency.
>> Right. And you know, this is still an intermediate level book, so it's not really expected that it will be a totally production ready system at the end, but it's still nice to show off the ability to do this stuff.
>> Sure exactly.
>> So another choice that you made with this project was to use a Rio or RIO as kind of the basis for the application itself. Why did you choose that?
>> Well, as, you know --- as anybody who has worked with Haskell a bit, for a bit, would know: the prelude in base is unfortunately still pretty broken. And it doesn't come with a lot of the stuff that you would end up using in pretty much any Haskell project. And so the rio package comes with two great things. One is the, you know, an alternative to the default prelude. The other is their Rio monad in which you're supposed to write the, you know, the entirety of your application. And I debated whether, you know, using the Rio monad in the project would have been a good idea. And it's probably --- it would have probably been too much to talk about. And it would have kind of, you know, shifted the focus a bit from let's actually use practical haskell and let's not focus on any specific library. But still, I love the fact that you can bring in the Rio prelude, and it comes with, you know, text. It comes with a lot of collections. You called it modules, out of the box. And it removes a lot of the partial functions that are available in the prelude in base. It's just a well-thought-out prelude. I really, really like it. And generally I like everything that Michael Snoyman puts out. Like, I use Stack all the time and, you know, Conduit is nice. a really nice package.
>> Yeah, he produces a lot of great tooling and libraries and stuff for the ecosystem. And Rio isn't something that I have actually used all that much, but I definitely appreciate the alternative prelude aspect, because like you say, the prelude in base has a strange amount of problems with it. Like it isn't safe, it has unsafe functions in it. And it doesn't give you a lot of the things that you might expect from a standard library, like a hash map or something like that. So, yeah. Pulling it all in with one library is super nice. And Rio isn't the only one, but it is a good one.
>> Sure, sure. There are others, for sure.
>> So speaking of Michael Snoyman, he had that blog post, I think it was a blog post, recently about either simple Haskell or boring Haskell. Was that him? And I can't remember which term it was.
>> Yeah, he called it boring Haskell.
>> Boring, okay. And I know you talk about this in the book a little bit. So could you --- could you talk about: what does that mean to you? And why did you choose to put it forward in this book?
>> Yeah, let me say, I've never talked to him and I don't think we actually, or rather, I don't think he actually agrees on a lot of the things I say about simple Haskell. And that probably his definition is different than mine. Although I do like what he said in that blog post that you talked about. But yeah, the main idea behind simple Haskell is that, you know, GHC comes with a lot of stuff. It lets you do basically anything in a million different ways. And that's because, you know, it has a huge heritage. It has been around for 30 years and it's been serving, somewhat surprisingly, like it's been serving successfully two very different crowds. On the one hand you have academia and language researchers. And on the other hand, you have the industry and people that use Haskell to write real world applications. And so, it is kind of natural for researchers to use this tool as a --- you know, as the tool to do their job. And so the outcome of that, for better or worse, is that we end up with a huge compiler with a ton of extensions available. Often the way they interact with one another is not very clear. Often they break the compiler in unexpected ways. And so --- and the other issue is that as a beginner or intermediate Haskeller, it's very hard to tell, you know, what are you supposed to use? Like what --- how do people even accomplish anything in this language on a day-to-day basis. With all the breadth of choice available. And so simple Haskell was like my --- was my way of saying: look, it's not that complicated. You don't need to understand category theory. You don't need to read all the papers that come out and that people discuss over and over. If you're unsure these are the set of extensions and the set of features that I find very useful and that I'm very productive with. And you know, it's not like a hard set of extensions that you ought to use, obviously. But it's a good starting point. And if you are in the same position as I was, where I was completely oblivious to what I was supposed to use and what I wasn't supposed to use, then I think having, you know, a good set of defaults would be pretty useful.
>> I agree. And I think especially for a beginner, it can be really valuable to have somebody who knows what they're doing say: just use this and it'll probably work pretty well. You know, it may not be best in the world, but it's not going to be bad and it'll work. And furthermore, I think that for --- in our community, in the Haskell community, there is a lot of advanced material. So stuff that's talking about, you know, the latest language extension that's only available in GHC head or like some effects system. And that's all really good and interesting, and I like reading about it, but at the same time, you don't need to know that stuff in order to implement, you know, really useful programs like a CI server. So, I think there is maybe room, like --- someone could take your book or the service you produce in your book and say: well, you know, let's throw an effect system at this and see what happens. Or let's throw this language extension. So it can be a nice way to, to contrast the simple versus the more complex
>> That would be, yeah, kind of interesting. love to see that.
>> The Complex Haskell Handbook. Somebody can write that one. And another thing that --- kind of related is that you throw in some language extensions that I would categorize as quality of life extensions. Like they don't really change your expressive power, like what you can do, but they make something nicer to use. So like block arguments, I think is a --- or lambda case. So what motivated you to throw those into the mix?
>> Yeah, exactly. So my --- I guess it's all about ergonomics. Like it's accepting the fact that Haskell 98 or Haskell 2010 is, as you say, sufficiently expressive for most day-to-day tasks. It still has some sharp edges that we can eliminate with some extensions that are, you know, only dealing with the ergonomics of the language. But they're not fundamentally changing the type system in any way. And so, you know, that's good enough for me. It makes the language nice to work with. And I find the type system and the type checker to be sufficiently powerful for my use cases. So that's good enough for me.
>> Yeah, I agree. And for those types of extensions, it's often syntactic sugar. So it's relatively easy to explain to a beginner, you know, If you turn on lambda case, you can write this form that is equal to this other form you might write. It's pretty straightforward.
>> Versus, you know, if you turn on, I don't know, data type contexts, what happens? I don't know. Go read a paper.
>> Yeah, yeah. Cross your fingers.
>> Right. So, like I was talking to you before the show started, I haven't had an opportunity to read the whole book. So we've hit the point now where we've talked about everything that I'm aware of in the book. What else is in there that I haven't asked you about?
>> Well, it kind of flows in a natural fashion, I would say. So if you --- if you've gone a quarter of the way in, the format stays pretty much the same all the way to the end. One thing that I find is particularly interesting is that we don't get to write the main function until the very last chapter, I think it is. So there's no actual running of the application until the very end. And all the --- like the way we make sure that we are writing the correct code is by writing integration tests. And, you know, they --- in the integration tests, we spin up actual Docker containers and we make sure that the builds run correctly. But we don't get to actually Stack run the application until the very end.
>> Yeah. And --- which, you know, it's something that --- again, another goal I had with this book was to actually showcase a lot of the things you constantly hear about Haskell. Like refactoring in Haskell is great. Or I don't run my --- I don't have to run my program to make sure that it's correct. I often, you know, talk with the compiler for two or three hours, and then only when it compiles, I give it a go just to make sure it runs. But I can be fairly confident that it would work. And so these two aspects were very important to me in the book. Like if you're writing a to-do list, you're not gonna appreciate how good the refactoring aspect is in Haskell. Whereas by starting with, you know, a simplified version of a CI server and reaching it as we go through the book, you get to see which type errors come up. And you get to see exactly how the compiler is helping you in fixing those errors. And maybe it's, you know, a case in a pattern match that's missing, or maybe the signature for a function has changed. You don't get really to to appreciate that with a toy project. You have to, you know, get a little bit more involved.
>> Right. You have to have something that works and does something, but then you, want to change what it does or add something to it. And then you're like, oh yeah, This is what refactoring is in Haskell.
>> Exactly. Which is amazing, but it's very hard to showcase it.
>> Right. Well, I look forward to getting to that part in the book and seeing that happen. I also got to say that I love the approach of working, not with the like top level executable, but with the individual pieces and testing those and, you know, to use the buzzword it's test driven development, which I'm a fan of but you don't really frame it as that in the book. It's just kind of like, let's write this thing and then let's prove that it works. Of course. What else would you do?
>> Yeah, I don't frame it like that because if I --- like, if I had --- if I said that it's TDD, you know, people would complain that it lacks, you know, a hundred unit tests for every little function that I have. So in general, even when I write for real world code, I tend to write bigger integration tests that kind of cover all of my bases instead of a million unit tests. Obviously it depends on what it is that I'm testing. But it kind of follows my approach in the real world as well. So are there a few very broad tests, and I'm okay with that. I find that it's a good balance between coverage and the amount of code.
>> Yeah, I like that approach as well. I think that aiming for like a hundred percent test coverage or writing a unit test for every function --- in the end, just makes it more difficult to refactor your code. Because you have to also deal with all these tests. And part of the appeal to me of writing tests in the first place is that it should make refactoring easier and more confident because I can run the test and make sure that everything still works. So it seems kind of self-defeating to write tests that make it harder to change your code.
>> Agreed, yeah. 100%.
>> Um, to throw another buzzword into the mix here, the way that you're describing the development of this application seems to me to be bottom up versus top down. So like, you know --- in opposite land, opposite you would write the book where you start with main equals undefined, and then you start filling that in. So is that how you approach development day to day?
>> Well, on a day to day basis, I'm much more --- like, I scramble all day long, essentially. But that's fine. Like that's where the fun is for me personally. And as long as you're not throwing, you know, crazy PRs out there, but you're all doing it on your local branch and it's somewhat look nice in the end. I'm fine with that. And I have to say that the way the book progresses is kind of artificial. Like it's very --- it is premeditated. Like all the little pieces and the way you add one thing after another, after another. And it all seems to flow together. It is, you know, it took me a while to figure out how to actually make it progress in a way that isn't constantly going back to something that we just changed. Or going back to a module that we haven't touched for a hundred pages. I really tried to make it flow as nicely as possible. And obviously when I'm writing an application, even when I was writing this application, my code was all over the place.
>> And I'm not ashamed to say that. I just think, you know --- it's fun for me to. And maybe it's my dynamically typed background where I used to do all sorts of crazy stuff. That's just the way I approach programming.
>> So you're telling me that the book was premeditated. You didn't live stream this whole book from start to finish?
>> Nah, it took me months. No no, definitely not.
>> Well, yeah. I was just, I mean --- same with TDD. You know, bottom up versus top down. It's not a hard dichotomy. It's not like oh, I do all my development top-down or all bottom up. But I think it can be interesting to approach problems in either or even both ways where you say, okay, I'm going to start top down, but then I kind of hit a roadblock and I don't really know where to go. So I'm going to flip and do bottom up for, awhile. and that's how I develop. And it sounds like maybe you're, you're similar.
>> Yeah, exactly. And, you know, with typed holes and the trick of putting undefined where you're not sure how to fill something, you know, you can really get far. And I think I use both tricks in the book. So that --- those are like the basic Swiss Army knives that all Haskellers should know. And it's, you know, it's great to talk about them.
>> Yeah. And in addition to like, highlighting how nice refactoring is in Haskell and how easy it is to change things, I think doing undefined and typed holes also shows like, I don't know, I guess it's kind of the initial refactoring, like, or the factoring, I guess the first one. It shows how nice it is to say, I don't know what goes here, but something does and I'll get to it later.
>> Yeah, yeah. It's really great.
>> And then you touched on something which I think is a bit of a meme either in the Haskell community or about the Haskell community, which is: once it compiles, it probably does what you expect. And I've found that to be largely true. Like, you know, there's some caveats and some asterisks there, but have you found that to be true as well?
>> Well, spoiler alert: it doesn't. So.
>> Well, there is --- like the beginning of part two of the book touches on this. And I think it's really, really important. Like, even if you get all of your --- like your program to compile and you use all the most advanced techniques to get the most correct program you could possibly get. At the end of the day, you're still talking with the other systems and you're still dealing with databases and networks. And that's where, you know, most errors come from. And so, even if we're writing our application in Haskell, it doesn't mean we can assume that everything else is gonna behave correctly. Because that's never going to be the case. And I find that in Haskell applications, a lot of the errors and bugs often stem from these, you know, glue code and plumbing that unfortunately is necessary to write and to deal with. And so, yeah. Having an application that compiles doesn't equal, it will run fine in production.
>> Right. Like even though you're making a valid HTTP request and all your types line up, still you're sending it over to, you know the Docker socket and maybe you typoed something inside one of those strings. Yeah,. that's where TDD comes back in. Very important to have those integration tests.
>> Cool. So is there anything else we haven't covered about the book that you want to get to?
>> I think we said pretty much everything.
>> So then now it's just: buy the book, right?
>> Cool. Well
>> So, yeah. I mean, clearly there's more to you than just the book. Is there anything else that you want to talk about, or that you want people to know about you?
>> Well, one topic that I kind of think about a lot is a future of programming languages. And whether I'd still be writing Haskell in 10 or 15 years. Or how Haskell is supposed to evolve, you know, to still be relevant and still be around in that timeframe. And, you know, I'm --- I mean, I'm always curious to know what other people think about the topic. And I can give you my take. And then we can maybe discuss this a bit. But I think this is very, very interesting topic that we can maybe
>> I agree! I think this is super interesting And I'm eager to hear your take.
>> Yeah, so. Despite everything we've talked about so far, about simple Haskell and keeping things simple and all that, I actually think for Haskell to be relevant in 15 years, it should embrace dependent types. Which is kind of counter intuitive, right? We said the opposite up until this point. But like, it seems to me that most mainstream languages will eventually catch up and will implement most of the Haskell features we know and love. Like I can't believe mainstream languages won't have union types and won't have exhaustive pattern matching, in 15 years time. And so Haskell has always been on the cutting edge. It's been around for 30 years, but what is going to make it relevant in another 15 years? And, you know, I --- if other, the programming languages evolve this way, and you know, other very nice languages come out during that timeframe. Like Scala three has just recently being released and it looks really, really nice with a nice syntax and all the crap about implicits removed. So --- and a very nice runtime as well, because the jVM is rock solid. So what is going to make me pick Haskell, you know, in 10 years time. And, you know, obviously dependent types are a big bet. We don't really know if they're going to work out. We don't really have a programming language is that are dependently typed outside of Idris and Agda, which we can agree nobody's using in production.
>> Yes, as good of a languages as they are.
>> Exactly, exactly. So, yeah, I'd be interested to know what you think about that. Whether Haskell can continue on this trajectory of kind of pleasing everybody. And having dependent types kind of bolted on with a set of extensions that are kind of fragile. whether it should go all in on that.
>> Yeah. I, think that --- so for me personally, I am not that excited about dependent types. I've played around with Idris and --- conceptually or intellectually, I really like the unification of like, let's not have a value level language and a type level language, and you can do different things in each of them and it's all arbitrary. So that totally makes sense, but like the actual ergonomics, or maybe the power to weight ratio, doesn't feel right for me. That being said, I think that, like we talked about with simple or boring Haskell, one of the challenges in Haskell is that there are so many language extensions that interact in weird ways. And with dependent types, I think most of them would be --- would go away, and be subsumed by the dependent type language extension. So, that might be nice. You know, rather than having at the top of your file, here's 20 lines of language extensions that you need in order to use Servant or something like that. Instead you just say, hey, I want dependent Haskell, and now I can do all this stuff in a really nice way. I think that would be great. So that's kinda my personal view, I guess. To your, you know, like --- Haskell has been on the cutting edge for so long and other languages are probably gonna pick up its features. I think that's true. It has been true and will continue to be true. You know, languages these days often have enums and pattern matching and exhaustiveness checking. So like, yeah. What will make Haskell unique? Why would you pick it instead of Scala? And dependent types is a good one. I think linear types could be in the mix as well, but then, you know, we have Rust with affine types, kind of proving that out. So yeah, maybe Haskell 15 years from now will be the pure, functional, lazy, dependently typed, linearly typed language. That's a lot of qualifiers.
>> Yeah, yeah. I mean, the thing you said about ergonomics, I think is really the core of the issue. Like using dependent types today is completely unergonomic, and that's what pushes me away from it. But we really don't have any data about what a dependently typed big application, would look like. So I'm really curious to see if that's the kind of path Haskell will go through. And, you know, with the Haskell Foundation setting the vision going forward, I'm really, really curious to see how things will evolve.
>> I am as well. And that actually reminds me, one thing that you could do today to kind of play around with dependently type Haskell would be to bolt on Liquid Haskell, right? As the --- I mean, refinement types are different than dependent types, but they're similar. So, you know, again, like, talking about some hypothetical complex Haskell handbook, that could be a way to augment this CI system, add liquid Haskell annotations to it.
>> Absolutely, yeah. It still feels kind of hacky. Like as much as I like the effort, I like --- I struggle to see myself in like using Liquid Haskell in --- today, as it is today. So again, I wonder what it --- if my opinion would change if we had a, you know, a compiler that understands dependent types at the core. And it's not something that's bolted on.
>> Right, yeah. It being integrated definitely makes a difference. In a previous life I worked with Clojure. And Clojure has a bolt-on type system called, or at the time it was called, core dot typed. I don't know if it's different now. And it's, you know, amazing that it works and it works reasonably well. But at the end of the day, it is an afterthought to the language and the ecosystem. So that made it not very nice to work with. As compared to, you know, Haskell or wherever where it's built in.
>> Yeah, for sure. Yeah. I am --- like, I'm also looking forward to seeing how projects like Unison evolve. That's another one that I'm keeping an eye on. I don't know. I think we're bound to see some innovation in the functional programming space. I think this is not the end of it. Like we have a rock solid production grade to compiler. And it's getting better by the day. But I think we will see some dramatic, you know, improvement one way or another in the coming years.
>> I'm very happy you brought up Unison. But I'm curious. What about it is appealing to you? Because I think from what I'm aware of, it has two kind of novel features. One is that it's more structured, right? It's like a Git repository for your functions and it stores them in a normalized form and you can do refactoring and all this stuff. And then also it has an effect system that is similar to the effect system like PureScript used to have, or that get mixed into the Haskell ecosystem. So is it one of those things that it appeals to you or something else?
>> Yeah, the effect system actually makes me cringe. I hated it when PureScript had it, and I'm glad they moved to a more, you know, IO like system. But I really liked the database aspect. Like, the fact that each function is its own definition. And, you know, that dramatically lowers the bar to collaboration and potentially open source contributions. Because then you can just provide that tiny little function and it becomes immediately available to, not only your project, but potentially all other projects, because it carries around all of its dependencies. And so, if such an ecosystem, with some sort of global database, where to spin up, I think that would be pretty game changing.
>> I agree. There have been so many times in Haskell and in every language I've worked with where there's some helper function deep in some package that I depend on and like --- or sorry that I don't depend on, and I'm like, well, do I want to pull in this giant package for this one tiny function? No. Or, okay, I'll just reimplement it myself, but that's a waste of effort. If I could just point to that one thing, that'd be great.
>> Exactly, exactly. Yeah.
>> Yeah. All right, Marco. Well, I think we've talked --- we've talked about a lot of great stuff here today. Is there anything else you want to talk about?
>> No, I think that's enough.
>> Okay. Yeah, we don't want to be here all day. Or, or maybe we do, we can always have your back.
>> For sure.
>> So yeah, it has been great talking with you and get to know you and exploring the book. Thank you for spending time with us today.
>> Thank you for having me. It's been great.
>> Okay, all right. And thank you listeners for listening to the Haskell Weekly podcast. I've been your host Taylor Fausak and with me today was Marco. You want to say your name?
>> Marco Sampellegrini.
>> Thank you. If you want to find out more about Haskell Weekly, you can go to our website, HaskellWeekly.News. And Marco, if people want to find out more about you, where should they go?
>> Well, given the complexity of my name, you can just look up simple Haskell book and something will come up. You will eventually land on my website with all of my profiles.
>> Sounds good. And we'll have links to those in the show notes as well. We are brought to you by our employer, ITProTV an ACI Learning company. And they would like to offer you 30% off the lifetime of your subscription by using promo code HaskellWeekly30 at itpro.tv. So that'll do it for us this week. And thank you for listening to the Haskell Weekly podcast. We'll see you next week. Bye.