Through the lens of Haskell: exploring new ideas for library design
Dubus, Georges
Georges Dubus - Through the lens of Haskell: exploring new ideas for library design Haskell is very different from Python, and provide different tools to library and framework designers. As a result, its ecosystem is filled with libraries and frameworks that solve the same problems we try to solve in our favorite programming languages, but with a very different approach. This talk is an exploration of the Haskell ecosystem, from the point of view of a Python developer. We will review various popular Haskell libraries and frameworks, focusing on the library design. The goal is to provide the audience a sneak peak of some different ways to tackle problems, and hopefully to inspire library authors to explore some design space that we don't usually explore in Python. This talk should be interesting to any intermediate Python programmer who is curious about other ways to solve problems. No Haskell knowledge is required from the audience.
 Okay, hi everyone. Let's talk a little bit about the kind of ideas we can steal from Askel to make better libraries. Okay, so I'm George, you can find me on Twitter, and as a way to procrastinate, I like learning new stuff, learning new languages, and this is a picture of me during the Django Girls workshop in Paris, and where I was coaching, and when I was undergoing questions, I was working on a bit of Askel code, so this is my face when I work on Askel. I learned a few interesting stuff, and I'm here to talk to you about some of the ideas I discovered. So last year, after European, there was a keynote about Askel. It was called What Python Can Learn from Askel. It was about Askel, the language, the strongly typed language with the huge compiler, and, well, Python has learned from Askel in the meantime. We know how to type annotations, and Guido talked about it yesterday, so we have learned from Askel. But talking about Askel, the language, it's very last year. It's a bit outdated, and we're not going to talk about the language. We're even going to suppose that it's the exact same language as Python. Let's say Askel is just a dialect of Python with slightly different syntax, but we don't care at all. What is interesting to us today is Askel the ecosystem, the community, and the kind of libraries that produce. On the left, you have the Python package index, and on the right, you have the Askel equivalent, the Askel package index. Let's see how the community differs, how the mindset differs, and what kind of ideas we can get from that. One of the ideas you'll find very often in the Haskell community is the idea of design space. The idea of design space is the idea that for a given problem, you have a lot of solutions. You have a full space of solutions for one single problem. Some of those solutions we know, and some we don't know yet. One idea that is very present in the Haskell community is that it is worth exploring the design space in search for new solutions that we don't know yet, and that might be more interesting than the one we have in regards to, well, maybe those are different solutions with different trade-offs that work better in some situations or are more general, so are faster to run or just easier to learn and to use. It's really the idea of there are areas, there are spaces we have to discover. In the Zen of Python, we say there should be one and preferably only one obvious way to do it. It's like Haskell adds, okay, let's keep looking for that obvious way. You'll often find new libraries or stuff that already exists, but which are different, make different exceptions and choose different trade-offs. Each time, this library, we try to compare as much as possible with the existing libraries. It's just not reinventing the wheel or doing something new because the other stuff were not invented here. It's really searching for a new, better, more interesting or just trying. That is not completely foreign to the Python ecosystem because a few years ago, Kinespree released the request library, which is a library for doing HTTP clients. There was already at the time many libraries to do HTTP clients, but this was a new one that tried to be as easy to use as possible. He has launched a movement called Python for Humans where he tries to encourage all of us to follow the idea of making libraries that are as simple and easy to use as possible. In a way, it's kind of trying to explore some new parts of the design space, some part where ease of use is the most important. We are now going to take a look at a few SQL libraries to see some parts of the design space we don't usually see in Python, but that are explored in the SQL community. Here you have on the left the top downloaded libraries in the Python package index. On the right, the top downloaded libraries in the SQL package index. When I said SQL and Python are similar, I wasn't lying. You see the same packages are downloaded in both cases. The most downloaded package is the JSON package. In both languages, you have multiple attempts to solve the packaging problem and you have some HTTP client libraries. But on the SQL side, you'll find a few libraries that do not have Python equivalent. Those are Lens, Atoparsec, or Conduit. I'm going to talk a little bit about them. First one is Atoparsec. I had to use Atoparsec in a project of mine, which is a slack bot that answers any line and the bot answers the next line. My girlfriend insisted that it's not a real life use case. The input of the bot is subtitled files, the one you download when you download a movie. I needed a way to pass those subtitles. There is a library in SQL that does that, which is called subtitle parser. This is the full definition of the package. When you open the documentation, this is all you will see. Just a little word about how to read this. When you have something with two columns, like parser, subtitle, it means there's something called parser-certi, which is type parser-subtitles. Subtitles is defined on the right. It's just a list of lines and lines and objects with following properties. All that interests me in this package is the parser of subtitle. I just told you what the subtitle is. A parser is kind of an object that is defined in the Atoparsec package. The way to use it is by using a function which is defined in the Atoparsec package, which is not the package where the subtitle parser live. That function is called parser-leaning, and it takes a parser-subtitle and byte string, which is just a string of bytes. It returns either a neural message or the subtitles I actually want. That's it. I use the parser from this library and the function from the other library, and I'm done. To be fair, this is not exactly how the function looks like because it's polymorphic on the type of object I want to parse. It takes any parser and a byte string and returns either the neural message or what the parser is supposed to parse. That is not the only way to use the parser. Atoparsec provides me a few other ways, like incremental parsing. Incremental parsing is when you have a very big set of data to parse, and you don't want to put it in memory before parsing it, so you feed it to the parser a little bit at a time. I can do that with the same parser I used in the previous function. Yet another way to use it is by using that parser to build other parses for bigger parsers. There's a lot of functions I can use to do that. Here are a few examples. I can use many to take a parser and get a parser that will parse a certain number of the single parser does. I can use all two with two parsers to get a parser that will parse either something or another thing, trying both and giving you what matches. All this way to use the parser are given to me by Atoparsec. The person who wrote the subtitle parser didn't care about any of that. That person wrote a 40 line library to parse subtitles, and I get a lot of ways to use it for free. There is a whole lot of other parsers built on the same principle. You'll find the package repository, a lot of packages to deal with CSV. You'll get a parser of CSV or a parser of JSON value, or a parser of ChromeTab if you want to read ChromeTab files, or a parser of email address that will return you a parser string that only if it matches an email address or if you need to work with normal files, you'll find a parser for that. Those are different libraries made by different people, and in every single of those libraries, there's only one thing that is useful, and one thing that is defined is the parser of the thing you want. Each of those libraries you can use with each of the ways to call, I just saw you. In every language, a good library simplifies the implementation, helps you write less lines of code, but in this situation, a good library helps you simplify the interface, and helps you write less documentation and less interface, and in the end, having less things to know before using your library. We have a generic solution, which is at the parser, the parsing solution, and a lot of specific building blocks that you just can plug in and plug in any without knowing any new things. The second library I would like to show in our exploration of that part of the design space is Conduix. Conduix is a streaming library. Streaming, meaning we have a long stream, a sequence of objects, of something, we don't want to treat them, handle them, but we don't want to load them all into memory when we do so. There are three concepts in Conduix, the producers, which just produce the stream of values, and the consumers, which just consume a stream of value and do something with it, and Conduix, which both consume in one side and produce something else on the other side. Once again, you will find a lot of those Conduix constructs in a lot of different libraries. For example, you can find somewhere in the Askeli repository a Conduix that gives you, what, sorry, functions that gives you a producer from a socket, a normal standard to unique socket, and you find a Conduix, the endosypt that is used to decompress a stream of bytes. And a sync, meaning a consumer that will just put what it gets into a file. And Conduix provides an operator, which is a by plugging operator, and you just plug, you just plug the different parts you have found in different libraries, you plug them together and you get this program that actually reads from the socket and just zip it and write it in a file. And every single of those parts was written by different people and can be found in a different library. And another way, another Conduix construct you can find is a function that just takes the parser we have seen five minutes ago and turn it into a Conduix. So now, with the 40 line little subtitle parsing library, I have a high-performance subtitle streaming library, which is not very useful, but still, and I can read from a subtitle file and pass every line as it goes and post it straight to IRC, there is actually an IRC consumer in the package repository. Don't do that, you're going to get banned from any IRC server, you try it, but you could, you could try. So once again, we find the same thing, you have a general solution for streaming, which is Conduix, and a lot of building blocks that's all at the same interface and are exchangeable and reasonable, built by a lot of different people. And the last library I'm going to show into, still into this exploration is Lens. The problem Lens tries to solve is data manipulation. So here is some data we can manipulate, it's a block post because everyone loves the example with block posts whose title is made up example considered harmful, and it has an annotator and some comments. And what Lens gives you is the abstraction of the idea of manipulating a piece of the data. In this case, we have title, which is a lens that points to the title of a block post. And I can use the view function with lens title and the block post and it's just a getter, it just returns the value pointed by the lens. But I can also combine to Lens with the dot, so the syntax is quite familiar. I have a lens that points to the hover of a block post and lens that points to the name of an author. I combine them with the dot and pass them to the view function and I get the name of the author. And I can use them as a setter. Just use the set function, pass it a lens, a new value and it returns a new block post with the value changed. And where it gets interesting is that lenses can also be used as getter setters for multiple values. In that case, we have commands which is a lens that points to the list of commands. But each is not exactly a lens, it's a traversal and that means the resulting commands dot each points to every single command in that list. And I can still combine it with a lens with author to get something which is called a traversal that points to every single author of a command in the block post object. I use the tool list function to get that list. The interesting part in that is that those getter pairs of lens and traversal are values. So if they are values, I can store them into a variable that I call command contents. So here is the traversal that points to every single content of a command in the block post. And I can use tool list of that value to get the list of commands. And I can use sets to change the content of every single command to blah, blah, blah because you shouldn't read the commands anyway. And if this is a value, I can put it in a variable. I can have a function return it and I can have a library return it. So I can put it in library and have an abstraction of data manipulation in library. And for example, there is one such library which lets you manipulate JSON with lenses. It provides just a handful of lenses with values which points to every single value in a JSON list. And key which takes an argument which is an attribute and points to the attribute of the JSON object. So with the same manipulation function provided by lens, you can now manipulate JSON directly. Another example which is provided another library which is provided is HTML. There are lenses to manipulate HTML. So we see HTML at these three with a lot of nodes. And we now have abstract data manipulation functions, objects, those lenses which let us look into the HTML. So simply we have one traversal name, all named which points to every single node in the HTML tree that has given name. And we combine it with lens contents which provide contents. And so this line is just all we need to define something that can get every single title in an HTML document. And so one last time, we have a general solution of data manipulation and a lot of building blocks in different libraries. So that's really a theme. That's something we can see a lot in Aska libraries that we don't really see in Python once again in their face for a lot of different libraries. So why am I telling you that? Just not because it's nice, but also because I think boring stealing ideas from other communities or the languages is the good way to produce excellent results. For example, I've talked about request a little earlier. Request provides very simple interface to make HTTP request. It provides a get function with text string which is the address of what you want and gives you a response object which is exactly what you need. And REC is a Haskell library which is heavily inspired by request. It provides the exact same get function with the same interface. It combines it with lens for the data manipulation part. So instead of doing request, you use the lens to get the content type, but that's exactly the same principle. This is the best Haskell library for making HTTP requests. And it's stolen seamlessly from Python because the Python library is an excellent idea. So taking ideas from other languages, I'll produce some libraries. And in the other direction, there is hypothesis which is a library for property-based testing. It is inspired by a library in Haskell called QuickCheck. And the main idea, it's a bit like unit test. Instead of making one example and checking your code work on that example, it will, you just say the property you want to check in this case. If I have a decode and encode function, I can't expect them to, well, if I decode then encode something, I want to get the initial stuff back. And hypothesis will make sure this is true for every single text. It can't generate. And it does really good generating analytics. And it will find every single corner case you have for code. And this is an excellent testing library. In Python, you can use it right now. It's awesome. And it was inspired by looking at what Haskell does. So as a conclusion, it was a bit fast, but more time for questions. I encourage you to explore the design space. Look at what exists and what doesn't exist. And make new stuff to solve existing problems differently. And every time explain what you did differently and why you did differently from what already exists. And in the direction you could look into that we don't usually explore in Python is factorized library interfaces. Make libraries that use other libraries for the interface so that a new library is just a single little stuff that you don't have to learn. You can just use it with what you already know. And the bonus conclusion is the do it yourself conclusion. Go learn something new, something else. Go learn Haskell or Erlango. Anything that's unusual. And see what part of the design space they explore and if it could fit into Python. And come back at your Python next year and make a presentation about what you learned in that new language. Thank you. Great talk. Does anybody have any questions? Any comments? Okay. I have a comment. It seems to me that in Python when there's several libraries that have the same interface, PEP comes up that sort of standardizes the interface. Like for databases we have a PEP that standardizes an interface. For HTTP servers we have FWISGI. Now there's async.io which kind of standardizes all the async stuff. Do you have any comments in that? Do you think the Haskell way is better? The problem with that is you can just really do a new library that will be that common interface. You have to go through the PEP process. Which means that you, I don't think I can create a PEP. But I can create a library for common interface. The other, the main reason why we do it that way in Python is because Haskell has a compiler that is able to check that the interface is respected by the library. In Python if you get a library that doesn't have the exact same interface you would expect, you'll just get an error at runtime. So well, we need PEP because we need an author, a strong source of definition of specification of what, how the interface should behave. Thank you. Anybody else? Yeah, I was thinking about kind of the same thing without strong, I'll mix them up, like without a possibility to define interfaces or protocols or however you call them. Do you even see a possibility to do something like this in Python or is it just like a strong sort of Haskell and those types of languages and like Python can do it but can maybe do other things better? The compiler checking type certainly helps but it's not necessary. In fact, we already have a few of those common interfaces in Python. What you mentioned, the databases or whisky have some plugins for web framework, our plugins for web framework all conform to one single interface and that works. So I think it is completely possible with what we currently have in Python that one single interface can be reused as long as that interface is specified and doesn't change. My question is kind of asking you to validate my opinion and it's somewhat related to what we were talking about. I thought that Haskell has this a lot that like a design pattern and software is encoded in a type but it's usually a best practice. So monads are one example and answers are another example. You think Python world would benefit more from having a standardized way to do things, standardized pattern always write classes in this way or something. I think that's a strong side of Haskell. So what do you think about this? I'm not sure. I completely get what you said. Sorry? It's a little bit of the same. One of the ideas hidden behind what I talked about is finding common patterns in different stuff and giving them a common interface which is not something we do that often in Python or maybe we do it but it's more organically. Multiple libraries converging to a common similar set of interface rather than one single formalized interface. I like the theme you draw about these generic libraries that provide the general solution and also the means of composition for the specific libraries. I'm wondering do you think there's something in Haskell that makes that more natural to do or easy to do? Are there like language features of Python that we should be using more or less in order to make that happen? As I said, I think the compiler telling you right away if you have the right interface helps but I think it's also a big part because of the mindset of well that's how people do it. The tools help sure but it's also the community and the way to do it. Any more questions? When do you use Python for what problems Haskell? That's a good question. Most of my projects nowadays because I don't work either with Python or Haskell, most of my projects are personal projects though. It's more take one technology and build something on it. I tend to alternate. Still I always use Python for small little things I need done in half an hour and nowadays I try to use Haskell to build bigger projects I think will get bigger because the way it works kind of helps to make something small then turn it into something bigger. Do you ever have the feeling that the best practice in Python to be Pythonic is holding the Python community back at looking into other communities for solutions for common problems that all programming languages and communities have? In Python there's this notion of code being Pythonic. Good Python code is Pythonic. What do people say? Is this wish to have a Pythonic solution holding us back in terms of looking for solutions in other languages that we can import back to Python? I don't know. You have two meanings to Pythonic. You have a low level Pythonic, single line Pythonic and you have a higher level. It's all solutions, architecture of solution Pythonic. And I guess no, you can find the language solution that we would call Pythonic, elegant structures and solutions to problem. So maybe the fact that the name is Pythonic prevents us in some way to look out. No, I think you can find the solution in another language and find it just as Pythonic as if it was written in Python. One more quick question. Welcome from me. Did you like the talk?
 Okay, hi everyone. Let's talk a little bit about the kind of ideas we can steal from  Askel to make better libraries. Okay, so I'm George, you can find me on Twitter, and as  a way to procrastinate, I like learning new stuff, learning new languages, and this is  a picture of me during the Django Girls workshop in Paris, and where I was coaching, and when  I was undergoing questions, I was working on a bit of Askel code, so this is my face  when I work on Askel. I learned a few interesting stuff, and I'm here to talk to you about some  of the ideas I discovered. So last year, after European, there was a keynote about Askel.  It was called What Python Can Learn from Askel. It was about Askel, the language, the strongly  typed language with the huge compiler, and, well, Python has learned from Askel in the  meantime. We know how to type annotations, and Guido talked about it yesterday, so we  have learned from Askel. But talking about Askel, the language, it's very last year.  It's a bit outdated, and we're not going to talk about the language. We're even going  to suppose that it's the exact same language as Python. Let's say Askel is just a dialect  of Python with slightly different syntax, but we don't care at all. What is interesting  to us today is Askel the ecosystem, the community, and the kind of libraries that produce. On  the left, you have the Python package index, and on the right, you have the Askel equivalent,  the Askel package index. Let's see how the community differs, how the mindset differs,  and what kind of ideas we can get from that. One of the ideas you'll find very often in  the Haskell community is the idea of design space. The idea of design space is the idea  that for a given problem, you have a lot of solutions. You have a full space of solutions  for one single problem. Some of those solutions we know, and some we don't know yet. One idea  that is very present in the Haskell community is that it is worth exploring the design space  in search for new solutions that we don't know yet, and that might be more interesting  than the one we have in regards to, well, maybe those are different solutions with different  trade-offs that work better in some situations or are more general, so are faster to run  or just easier to learn and to use. It's really the idea of there are areas, there are spaces  we have to discover. In the Zen of Python, we say there should be one and preferably  only one obvious way to do it. It's like Haskell adds, okay, let's keep looking for that obvious  way. You'll often find new libraries or stuff that already exists, but which are different,  make different exceptions and choose different trade-offs. Each time, this library, we try  to compare as much as possible with the existing libraries. It's just not reinventing the wheel  or doing something new because the other stuff were not invented here. It's really searching  for a new, better, more interesting or just trying. That is not completely foreign to  the Python ecosystem because a few years ago, Kinespree released the request library, which  is a library for doing HTTP clients. There was already at the time many libraries to do  HTTP clients, but this was a new one that tried to be as easy to use as possible. He  has launched a movement called Python for Humans where he tries to encourage all of  us to follow the idea of making libraries that are as simple and easy to use as possible.  In a way, it's kind of trying to explore some new parts of the design space, some part where  ease of use is the most important. We are now going to take a look at a few SQL libraries  to see some parts of the design space we don't usually see in Python, but that are explored  in the SQL community. Here you have on the left the top downloaded libraries in the Python  package index. On the right, the top downloaded libraries in the SQL package index. When I  said SQL and Python are similar, I wasn't lying. You see the same packages are downloaded  in both cases. The most downloaded package is the JSON package. In both languages, you  have multiple attempts to solve the packaging problem and you have some HTTP client libraries.  But on the SQL side, you'll find a few libraries that do not have Python equivalent. Those  are Lens, Atoparsec, or Conduit. I'm going to talk a little bit about them. First one  is Atoparsec. I had to use Atoparsec in a project of mine, which is a slack bot that  answers any line and the bot answers the next line. My girlfriend insisted that it's not  a real life use case. The input of the bot is subtitled files, the one you download when  you download a movie. I needed a way to pass those subtitles. There is a library in SQL  that does that, which is called subtitle parser. This is the full definition of the package.  When you open the documentation, this is all you will see. Just a little word about how  to read this. When you have something with two columns, like parser, subtitle, it means  there's something called parser-certi, which is type parser-subtitles. Subtitles is defined  on the right. It's just a list of lines and lines and objects with following properties.  All that interests me in this package is the parser of subtitle. I just told you what the  subtitle is. A parser is kind of an object that is defined in the Atoparsec package. The  way to use it is by using a function which is defined in the Atoparsec package, which  is not the package where the subtitle parser live. That function is called parser-leaning,  and it takes a parser-subtitle and byte string, which is just a string of bytes. It returns  either a neural message or the subtitles I actually want. That's it. I use the parser  from this library and the function from the other library, and I'm done. To be fair, this  is not exactly how the function looks like because it's polymorphic on the type of object  I want to parse. It takes any parser and a byte string and returns either the neural  message or what the parser is supposed to parse. That is not the only way to use the  parser. Atoparsec provides me a few other ways, like incremental parsing. Incremental  parsing is when you have a very big set of data to parse, and you don't want to put it  in memory before parsing it, so you feed it to the parser a little bit at a time. I can  do that with the same parser I used in the previous function. Yet another way to use  it is by using that parser to build other parses for bigger parsers. There's a lot of  functions I can use to do that. Here are a few examples. I can use many to take a parser  and get a parser that will parse a certain number of the single parser does. I can use  all two with two parsers to get a parser that will parse either something or another thing,  trying both and giving you what matches. All this way to use the parser are given to me  by Atoparsec. The person who wrote the subtitle parser didn't care about any of that. That  person wrote a 40 line library to parse subtitles, and I get a lot of ways to use it for free.  There is a whole lot of other parsers built on the same principle. You'll find the package  repository, a lot of packages to deal with CSV. You'll get a parser of CSV or a parser  of JSON value, or a parser of ChromeTab if you want to read ChromeTab files, or a parser  of email address that will return you a parser string that only if it matches an email address  or if you need to work with normal files, you'll find a parser for that. Those are different  libraries made by different people, and in every single of those libraries, there's only  one thing that is useful, and one thing that is defined is the parser of the thing you  want. Each of those libraries you can use with each of the ways to call, I just saw  you. In every language, a good library simplifies the implementation, helps you write less lines  of code, but in this situation, a good library helps you simplify the interface, and helps  you write less documentation and less interface, and in the end, having less things to know  before using your library. We have a generic solution, which is at the  parser, the parsing solution, and a lot of specific building blocks that you just can  plug in and plug in any without knowing any new things. The second library I would like  to show in our exploration of that part of the design space is Conduix. Conduix is a  streaming library. Streaming, meaning we have a long stream, a sequence of objects, of something,  we don't want to treat them, handle them, but we don't want to load them all into memory  when we do so. There are three concepts in Conduix, the producers, which just produce  the stream of values, and the consumers, which just consume a stream of value and do something  with it, and Conduix, which both consume in one side and produce something else on the  other side. Once again, you will find a lot of those Conduix constructs in a lot of different  libraries. For example, you can find somewhere in the Askeli repository a Conduix that gives  you, what, sorry, functions that gives you a producer from a socket, a normal standard  to unique socket, and you find a Conduix, the endosypt that is used to decompress a  stream of bytes. And a sync, meaning a consumer that will just put what it gets into a file.  And Conduix provides an operator, which is a by plugging operator, and you just plug,  you just plug the different parts you have found in different libraries, you plug them  together and you get this program that actually reads from the socket and just zip it and write  it in a file. And every single of those parts was written by different people and can be  found in a different library. And another way, another Conduix construct you can find  is a function that just takes the parser we have seen five minutes ago and turn it into  a Conduix. So now, with the 40 line little subtitle parsing library, I have a high-performance  subtitle streaming library, which is not very useful, but still, and I can read from  a subtitle file and pass every line as it goes and post it straight to IRC, there is  actually an IRC consumer in the package repository. Don't do that, you're going to get banned  from any IRC server, you try it, but you could, you could try. So once again, we find the  same thing, you have a general solution for streaming, which is Conduix, and a lot of  building blocks that's all at the same interface and are exchangeable and reasonable, built  by a lot of different people. And the last library I'm going to show into, still into  this exploration is Lens. The problem Lens tries to solve is data manipulation. So here  is some data we can manipulate, it's a block post because everyone loves the example with  block posts whose title is made up example considered harmful, and it has an annotator  and some comments. And what Lens gives you is the abstraction of the idea of manipulating  a piece of the data. In this case, we have title, which is a lens that points to the  title of a block post. And I can use the view function with lens title and the block post  and it's just a getter, it just returns the value pointed by the lens. But I can also  combine to Lens with the dot, so the syntax is quite familiar. I have a lens that points  to the hover of a block post and lens that points to the name of an author. I combine  them with the dot and pass them to the view function and I get the name of the author.  And I can use them as a setter. Just use the set function, pass it a lens, a new value  and it returns a new block post with the value changed. And where it gets interesting is  that lenses can also be used as getter setters for multiple values. In that case, we have  commands which is a lens that points to the list of commands. But each is not exactly  a lens, it's a traversal and that means the resulting commands dot each points to every  single command in that list. And I can still combine it with a lens with author to get  something which is called a traversal that points to every single author of a command  in the block post object. I use the tool list function to get that list. The interesting  part in that is that those getter pairs of lens and traversal are values. So if they  are values, I can store them into a variable that I call command contents. So here is the  traversal that points to every single content of a command in the block post. And I can  use tool list of that value to get the list of commands. And I can use sets to change  the content of every single command to blah, blah, blah because you shouldn't read the  commands anyway. And if this is a value, I can put it in a variable. I can have a function  return it and I can have a library return it. So I can put it in library and have an  abstraction of data manipulation in library. And for example, there is one such library  which lets you manipulate JSON with lenses. It provides just a handful of lenses with  values which points to every single value in a JSON list. And key which takes an argument  which is an attribute and points to the attribute of the JSON object. So with the same manipulation  function provided by lens, you can now manipulate JSON directly. Another example which is provided  another library which is provided is HTML. There are lenses to manipulate HTML. So we  see HTML at these three with a lot of nodes. And we now have abstract data manipulation  functions, objects, those lenses which let us look into the HTML. So simply we have one  traversal name, all named which points to every single node in the HTML tree that has  given name. And we combine it with lens contents which provide contents. And so this line is  just all we need to define something that can get every single title in an HTML document.  And so one last time, we have a general solution of data manipulation and a lot of building  blocks in different libraries. So that's really a theme. That's something we can see a lot  in Aska libraries that we don't really see in Python once again in their face for a lot  of different libraries. So why am I telling you that? Just not because it's nice, but  also because I think boring stealing ideas from other communities or the languages is  the good way to produce excellent results. For example, I've talked about request a little  earlier. Request provides very simple interface to make HTTP request. It provides a get function  with text string which is the address of what you want and gives you a response object which  is exactly what you need. And REC is a Haskell library which is heavily inspired by request.  It provides the exact same get function with the same interface. It combines it with lens  for the data manipulation part. So instead of doing request, you use the lens to get  the content type, but that's exactly the same principle. This is the best Haskell library  for making HTTP requests. And it's stolen seamlessly from Python because the Python  library is an excellent idea. So taking ideas from other languages, I'll produce some libraries.  And in the other direction, there is hypothesis which is a library for property-based testing.  It is inspired by a library in Haskell called QuickCheck. And the main idea, it's a bit like  unit test. Instead of making one example and checking your code work on that example, it  will, you just say the property you want to check in this case. If I have a decode and  encode function, I can't expect them to, well, if I decode then encode something, I want  to get the initial stuff back. And hypothesis will make sure this is true for every single  text. It can't generate. And it does really good generating analytics. And it will find  every single corner case you have for code. And this is an excellent testing library.  In Python, you can use it right now. It's awesome. And it was inspired by looking at  what Haskell does. So as a conclusion, it was a bit fast, but more time for questions.  I encourage you to explore the design space. Look at what exists and what doesn't exist.  And make new stuff to solve existing problems differently. And every time explain what you  did differently and why you did differently from what already exists. And in the direction  you could look into that we don't usually explore in Python is factorized library interfaces.  Make libraries that use other libraries for the interface so that a new library is just  a single little stuff that you don't have to learn. You can just use it with what you  already know. And the bonus conclusion is the do it yourself conclusion. Go learn something  new, something else. Go learn Haskell or Erlango. Anything that's unusual. And see what part  of the design space they explore and if it could fit into Python. And come back at your  Python next year and make a presentation about what you learned in that new language. Thank  you.  Great talk. Does anybody have any questions? Any comments? Okay. I have a comment. It seems  to me that in Python when there's several libraries that have the same interface, PEP  comes up that sort of standardizes the interface. Like for databases we have a PEP that standardizes  an interface. For HTTP servers we have FWISGI. Now there's async.io which kind of standardizes  all the async stuff. Do you have any comments in that? Do you think the Haskell way is better?  The problem with that is you can just really do a new library that will be that common  interface. You have to go through the PEP process. Which means that you, I don't think  I can create a PEP. But I can create a library for common interface. The other, the main  reason why we do it that way in Python is because Haskell has a compiler that is able  to check that the interface is respected by the library. In Python if you get a library  that doesn't have the exact same interface you would expect, you'll just get an error  at runtime. So well, we need PEP because we need an author, a strong source of definition  of specification of what, how the interface should behave.  Thank you. Anybody else?  Yeah, I was thinking about kind of the same thing without strong, I'll mix them up, like  without a possibility to define interfaces or protocols or however you call them. Do  you even see a possibility to do something like this in Python or is it just like a strong  sort of Haskell and those types of languages and like Python can do it but can maybe do  other things better?  The compiler checking type certainly helps but it's not necessary. In fact, we already  have a few of those common interfaces in Python. What you mentioned, the databases or whisky  have some plugins for web framework, our plugins for web framework all conform to one single  interface and that works. So I think it is completely possible with what we currently  have in Python that one single interface can be reused as long as that interface is specified  and doesn't change.  My question is kind of asking you to validate my opinion and it's somewhat related to what  we were talking about. I thought that Haskell has this a lot that like a design pattern  and software is encoded in a type but it's usually a best practice. So monads are one  example and answers are another example. You think Python world would benefit more from  having a standardized way to do things, standardized pattern always write classes in this way or  something. I think that's a strong side of Haskell. So what do you think about this?  I'm not sure. I completely get what you said. Sorry?  It's a little bit of the same. One of the ideas hidden behind what I talked about is  finding common patterns in different stuff and giving them a common interface which is  not something we do that often in Python or maybe we do it but it's more organically.  Multiple libraries converging to a common similar set of interface rather than one single  formalized interface. I like the theme you draw about these generic  libraries that provide the general solution and also the means of composition for the  specific libraries. I'm wondering do you think there's something in Haskell that makes that  more natural to do or easy to do? Are there like language features of Python that we should  be using more or less in order to make that happen?  As I said, I think the compiler telling you right away if you have the right interface  helps but I think it's also a big part because of the mindset of well that's how people  do it. The tools help sure but it's also the community and the way to do it.  Any more questions?  When do you use Python for what problems Haskell?  That's a good question. Most of my projects nowadays because I don't work either with  Python or Haskell, most of my projects are personal projects though. It's more take one  technology and build something on it. I tend to alternate. Still I always use Python for  small little things I need done in half an hour and nowadays I try to use Haskell to  build bigger projects I think will get bigger because the way it works kind of helps to  make something small then turn it into something bigger.  Do you ever have the feeling that the best practice in Python to be Pythonic is holding  the Python community back at looking into other communities for solutions for common  problems that all programming languages and communities have?  In Python there's this notion of code being Pythonic. Good Python code is Pythonic. What  do people say? Is this wish to have a Pythonic solution holding us back in terms of looking  for solutions in other languages that we can import back to Python?  I don't know. You have two meanings to Pythonic. You have a low level Pythonic, single line  Pythonic and you have a higher level. It's all solutions, architecture of solution Pythonic.  And I guess no, you can find the language solution that we would call Pythonic, elegant  structures and solutions to problem. So maybe the fact that the name is Pythonic  prevents us in some way to look out. No, I think you can find the solution in another  language and find it just as Pythonic as if it was written in Python.  One more quick question. Welcome from me. Did you like the talk?
Georges_Dubus_-_Through_the_lens_of_Haskell__exploring_new_ideas_for_library_design_0_4043.png Georges_Dubus_-_Through_the_lens_of_Haskell__exploring_new_ideas_for_library_design_4044_5519.png Georges_Dubus_-_Through_the_lens_of_Haskell__exploring_new_ideas_for_library_design_5520_6995.png Georges_Dubus_-_Through_the_lens_of_Haskell__exploring_new_ideas_for_library_design_6996_8267.png Georges_Dubus_-_Through_the_lens_of_Haskell__exploring_new_ideas_for_library_design_8268_8351.png Georges_Dubus_-_Through_the_lens_of_Haskell__exploring_new_ideas_for_library_design_8352_10619.png Georges_Dubus_-_Through_the_lens_of_Haskell__exploring_new_ideas_for_library_design_10620_12419.png Georges_Dubus_-_Through_the_lens_of_Haskell__exploring_new_ideas_for_library_design_12420_12587.png Georges_Dubus_-_Through_the_lens_of_Haskell__exploring_new_ideas_for_library_design_12588_12911.png Georges_Dubus_-_Through_the_lens_of_Haskell__exploring_new_ideas_for_library_design_12912_15623.png Georges_Dubus_-_Through_the_lens_of_Haskell__exploring_new_ideas_for_library_design_15624_15731.png Georges_Dubus_-_Through_the_lens_of_Haskell__exploring_new_ideas_for_library_design_15732_16283.png Georges_Dubus_-_Through_the_lens_of_Haskell__exploring_new_ideas_for_library_design_16284_18035.png Georges_Dubus_-_Through_the_lens_of_Haskell__exploring_new_ideas_for_library_design_18036_18131.png Georges_Dubus_-_Through_the_lens_of_Haskell__exploring_new_ideas_for_library_design_18132_18335.png Georges_Dubus_-_Through_the_lens_of_Haskell__exploring_new_ideas_for_library_design_18336_19019.png Georges_Dubus_-_Through_the_lens_of_Haskell__exploring_new_ideas_for_library_design_19020_19583.png Georges_Dubus_-_Through_the_lens_of_Haskell__exploring_new_ideas_for_library_design_19584_20051.png Georges_Dubus_-_Through_the_lens_of_Haskell__exploring_new_ideas_for_library_design_20052_21383.png Georges_Dubus_-_Through_the_lens_of_Haskell__exploring_new_ideas_for_library_design_21384_21923.png Georges_Dubus_-_Through_the_lens_of_Haskell__exploring_new_ideas_for_library_design_21924_22379.png Georges_Dubus_-_Through_the_lens_of_Haskell__exploring_new_ideas_for_library_design_22380_23951.png Georges_Dubus_-_Through_the_lens_of_Haskell__exploring_new_ideas_for_library_design_23952_24167.png Georges_Dubus_-_Through_the_lens_of_Haskell__exploring_new_ideas_for_library_design_24168_25823.png Georges_Dubus_-_Through_the_lens_of_Haskell__exploring_new_ideas_for_library_design_25824_29939.png Georges_Dubus_-_Through_the_lens_of_Haskell__exploring_new_ideas_for_library_design_29940_33455.png Georges_Dubus_-_Through_the_lens_of_Haskell__exploring_new_ideas_for_library_design_33456_39119.png Georges_Dubus_-_Through_the_lens_of_Haskell__exploring_new_ideas_for_library_design_39120_44298.png
Okay, hi everyone. Let's talk a little bit about the kind of ideas we can steal from Askel to make better libraries. Okay, so I'm George, you can find me on Twitter, and as a way to procrastinate, I like learning new stuff, learning new languages, and this is a picture of me during the Django Girls workshop in Paris, and where I was coaching, and when I was undergoing questions, I was working on a bit of Askel code, so this is my face when I work on Askel. I learned a few interesting stuff, and I'm here to talk to you about some of the ideas I discovered. So last year, after European, there was a keynote about Askel. It was called What Python Can Learn from Askel. It was about Askel, the language, the strongly typed language with the huge compiler, and, well, Python has learned from Askel in the meantime. We know how to type annotations, and Guido talked about it yesterday, so we have learned from Askel. But talking about Askel, the language, it's very last year. It's a bit outdated, and we're not going to talk about the language. We're even going to suppose that it's the exact same language as Python. Let's say Askel is just a dialect of Python with slightly different syntax, but we don't care at all. What is interesting to us today is Askel the ecosystem, the community, and the kind of libraries that produce. On the left, you have the Python package index, and on the right, you have the Askel equivalent, the Askel package index. Let's see how the community differs, how the mindset differs, and what kind of ideas we can get from that. One of the ideas you'll find very often in the Haskell community is the idea of design space. The idea of design space is the idea that for a given problem, you have a lot of solutions. You have a full space of solutions for one single problem. Some of those solutions we know, and some we don't know yet. One idea that is very present in the Haskell community is that it is worth exploring the design space in search for new solutions that we don't know yet, and that might be more interesting than the one we have in regards to, well, maybe those are different solutions with different trade-offs that work better in some situations or are more general, so are faster to run or just easier to learn and to use. It's really the idea of there are areas, there are spaces we have to discover. In the Zen of Python, we say there should be one and preferably only one obvious way to do it. It's like Haskell adds, okay, let's keep looking for that obvious way. You'll often find new libraries or stuff that already exists, but which are different, make different exceptions and choose different trade-offs. Each time, this library, we try to compare as much as possible with the existing libraries. It's just not reinventing the wheel or doing something new because the other stuff were not invented here. It's really searching for a new, better, more interesting or just trying. That is not completely foreign to the Python ecosystem because a few years ago, Kinespree released the request library, which is a library for doing HTTP clients. There was already at the time many libraries to do HTTP clients, but this was a new one that tried to be as easy to use as possible. He has launched a movement called Python for Humans where he tries to encourage all of us to follow the idea of making libraries that are as simple and easy to use as possible. In a way, it's kind of trying to explore some new parts of the design space, some part where ease of use is the most important. We are now going to take a look at a few SQL libraries to see some parts of the design space we don't usually see in Python, but that are explored in the SQL community. Here you have on the left the top downloaded libraries in the Python package index. On the right, the top downloaded libraries in the SQL package index. When I said SQL and Python are similar, I wasn't lying. You see the same packages are downloaded in both cases. The most downloaded package is the JSON package. In both languages, you have multiple attempts to solve the packaging problem and you have some HTTP client libraries. But on the SQL side, you'll find a few libraries that do not have Python equivalent. Those are Lens, Atoparsec, or Conduit. I'm going to talk a little bit about them. First one is Atoparsec. I had to use Atoparsec in a project of mine, which is a slack bot that answers any line and the bot answers the next line. My girlfriend insisted that it's not a real life use case. The input of the bot is subtitled files, the one you download when you download a movie. I needed a way to pass those subtitles. There is a library in SQL that does that, which is called subtitle parser. This is the full definition of the package. When you open the documentation, this is all you will see. Just a little word about how to read this. When you have something with two columns, like parser, subtitle, it means there's something called parser-certi, which is type parser-subtitles. Subtitles is defined on the right. It's just a list of lines and lines and objects with following properties. All that interests me in this package is the parser of subtitle. I just told you what the subtitle is. A parser is kind of an object that is defined in the Atoparsec package. The way to use it is by using a function which is defined in the Atoparsec package, which is not the package where the subtitle parser live. That function is called parser-leaning, and it takes a parser-subtitle and byte string, which is just a string of bytes. It returns either a neural message or the subtitles I actually want. That's it. I use the parser from this library and the function from the other library, and I'm done. To be fair, this is not exactly how the function looks like because it's polymorphic on the type of object I want to parse. It takes any parser and a byte string and returns either the neural message or what the parser is supposed to parse. That is not the only way to use the parser. Atoparsec provides me a few other ways, like incremental parsing. Incremental parsing is when you have a very big set of data to parse, and you don't want to put it in memory before parsing it, so you feed it to the parser a little bit at a time. I can do that with the same parser I used in the previous function. Yet another way to use it is by using that parser to build other parses for bigger parsers. There's a lot of functions I can use to do that. Here are a few examples. I can use many to take a parser and get a parser that will parse a certain number of the single parser does. I can use all two with two parsers to get a parser that will parse either something or another thing, trying both and giving you what matches. All this way to use the parser are given to me by Atoparsec. The person who wrote the subtitle parser didn't care about any of that. That person wrote a 40 line library to parse subtitles, and I get a lot of ways to use it for free. There is a whole lot of other parsers built on the same principle. You'll find the package repository, a lot of packages to deal with CSV. You'll get a parser of CSV or a parser of JSON value, or a parser of ChromeTab if you want to read ChromeTab files, or a parser of email address that will return you a parser string that only if it matches an email address or if you need to work with normal files, you'll find a parser for that. Those are different libraries made by different people, and in every single of those libraries, there's only one thing that is useful, and one thing that is defined is the parser of the thing you want. Each of those libraries you can use with each of the ways to call, I just saw you. In every language, a good library simplifies the implementation, helps you write less lines of code, but in this situation, a good library helps you simplify the interface, and helps you write less documentation and less interface, and in the end, having less things to know before using your library. We have a generic solution, which is at the parser, the parsing solution, and a lot of specific building blocks that you just can plug in and plug in any without knowing any new things. The second library I would like to show in our exploration of that part of the design space is Conduix. Conduix is a streaming library. Streaming, meaning we have a long stream, a sequence of objects, of something, we don't want to treat them, handle them, but we don't want to load them all into memory when we do so. There are three concepts in Conduix, the producers, which just produce the stream of values, and the consumers, which just consume a stream of value and do something with it, and Conduix, which both consume in one side and produce something else on the other side. Once again, you will find a lot of those Conduix constructs in a lot of different libraries. For example, you can find somewhere in the Askeli repository a Conduix that gives you, what, sorry, functions that gives you a producer from a socket, a normal standard to unique socket, and you find a Conduix, the endosypt that is used to decompress a stream of bytes. And a sync, meaning a consumer that will just put what it gets into a file. And Conduix provides an operator, which is a by plugging operator, and you just plug, you just plug the different parts you have found in different libraries, you plug them together and you get this program that actually reads from the socket and just zip it and write it in a file. And every single of those parts was written by different people and can be found in a different library. And another way, another Conduix construct you can find is a function that just takes the parser we have seen five minutes ago and turn it into a Conduix. So now, with the 40 line little subtitle parsing library, I have a high-performance subtitle streaming library, which is not very useful, but still, and I can read from a subtitle file and pass every line as it goes and post it straight to IRC, there is actually an IRC consumer in the package repository. Don't do that, you're going to get banned from any IRC server, you try it, but you could, you could try. So once again, we find the same thing, you have a general solution for streaming, which is Conduix, and a lot of building blocks that's all at the same interface and are exchangeable and reasonable, built by a lot of different people. And the last library I'm going to show into, still into this exploration is Lens. The problem Lens tries to solve is data manipulation. So here is some data we can manipulate, it's a block post because everyone loves the example with block posts whose title is made up example considered harmful, and it has an annotator and some comments. And what Lens gives you is the abstraction of the idea of manipulating a piece of the data. In this case, we have title, which is a lens that points to the title of a block post. And I can use the view function with lens title and the block post and it's just a getter, it just returns the value pointed by the lens. But I can also combine to Lens with the dot, so the syntax is quite familiar. I have a lens that points to the hover of a block post and lens that points to the name of an author. I combine them with the dot and pass them to the view function and I get the name of the author. And I can use them as a setter. Just use the set function, pass it a lens, a new value and it returns a new block post with the value changed. And where it gets interesting is that lenses can also be used as getter setters for multiple values. In that case, we have commands which is a lens that points to the list of commands. But each is not exactly a lens, it's a traversal and that means the resulting commands dot each points to every single command in that list. And I can still combine it with a lens with author to get something which is called a traversal that points to every single author of a command in the block post object. I use the tool list function to get that list. The interesting part in that is that those getter pairs of lens and traversal are values. So if they are values, I can store them into a variable that I call command contents. So here is the traversal that points to every single content of a command in the block post. And I can use tool list of that value to get the list of commands. And I can use sets to change the content of every single command to blah, blah, blah because you shouldn't read the commands anyway. And if this is a value, I can put it in a variable. I can have a function return it and I can have a library return it. So I can put it in library and have an abstraction of data manipulation in library. And for example, there is one such library which lets you manipulate JSON with lenses. It provides just a handful of lenses with values which points to every single value in a JSON list. And key which takes an argument which is an attribute and points to the attribute of the JSON object. So with the same manipulation function provided by lens, you can now manipulate JSON directly. Another example which is provided another library which is provided is HTML. There are lenses to manipulate HTML. So we see HTML at these three with a lot of nodes. And we now have abstract data manipulation functions, objects, those lenses which let us look into the HTML. So simply we have one traversal name, all named which points to every single node in the HTML tree that has given name. And we combine it with lens contents which provide contents. And so this line is just all we need to define something that can get every single title in an HTML document. And so one last time, we have a general solution of data manipulation and a lot of building blocks in different libraries. So that's really a theme. That's something we can see a lot in Aska libraries that we don't really see in Python once again in their face for a lot of different libraries. So why am I telling you that? Just not because it's nice, but also because I think boring stealing ideas from other communities or the languages is the good way to produce excellent results. For example, I've talked about request a little earlier. Request provides very simple interface to make HTTP request. It provides a get function with text string which is the address of what you want and gives you a response object which is exactly what you need. And REC is a Haskell library which is heavily inspired by request. It provides the exact same get function with the same interface. It combines it with lens for the data manipulation part. So instead of doing request, you use the lens to get the content type, but that's exactly the same principle. This is the best Haskell library for making HTTP requests. And it's stolen seamlessly from Python because the Python library is an excellent idea. So taking ideas from other languages, I'll produce some libraries. And in the other direction, there is hypothesis which is a library for property-based testing. It is inspired by a library in Haskell called QuickCheck. And the main idea, it's a bit like unit test. Instead of making one example and checking your code work on that example, it will, you just say the property you want to check in this case. If I have a decode and encode function, I can't expect them to, well, if I decode then encode something, I want to get the initial stuff back. And hypothesis will make sure this is true for every single text. It can't generate. And it does really good generating analytics. And it will find every single corner case you have for code. And this is an excellent testing library. In Python, you can use it right now. It's awesome. And it was inspired by looking at what Haskell does. So as a conclusion, it was a bit fast, but more time for questions. I encourage you to explore the design space. Look at what exists and what doesn't exist. And make new stuff to solve existing problems differently. And every time explain what you did differently and why you did differently from what already exists. And in the direction you could look into that we don't usually explore in Python is factorized library interfaces. Make libraries that use other libraries for the interface so that a new library is just a single little stuff that you don't have to learn. You can just use it with what you already know. And the bonus conclusion is the do it yourself conclusion. Go learn something new, something else. Go learn Haskell or Erlango. Anything that's unusual. And see what part of the design space they explore and if it could fit into Python. And come back at your Python next year and make a presentation about what you learned in that new language. Thank you. Great talk. Does anybody have any questions? Any comments? Okay. I have a comment. It seems to me that in Python when there's several libraries that have the same interface, PEP comes up that sort of standardizes the interface. Like for databases we have a PEP that standardizes an interface. For HTTP servers we have FWISGI. Now there's async.io which kind of standardizes all the async stuff. Do you have any comments in that? Do you think the Haskell way is better? The problem with that is you can just really do a new library that will be that common interface. You have to go through the PEP process. Which means that you, I don't think I can create a PEP. But I can create a library for common interface. The other, the main reason why we do it that way in Python is because Haskell has a compiler that is able to check that the interface is respected by the library. In Python if you get a library that doesn't have the exact same interface you would expect, you'll just get an error at runtime. So well, we need PEP because we need an author, a strong source of definition of specification of what, how the interface should behave. Thank you. Anybody else? Yeah, I was thinking about kind of the same thing without strong, I'll mix them up, like without a possibility to define interfaces or protocols or however you call them. Do you even see a possibility to do something like this in Python or is it just like a strong sort of Haskell and those types of languages and like Python can do it but can maybe do other things better? The compiler checking type certainly helps but it's not necessary. In fact, we already have a few of those common interfaces in Python. What you mentioned, the databases or whisky have some plugins for web framework, our plugins for web framework all conform to one single interface and that works. So I think it is completely possible with what we currently have in Python that one single interface can be reused as long as that interface is specified and doesn't change. My question is kind of asking you to validate my opinion and it's somewhat related to what we were talking about. I thought that Haskell has this a lot that like a design pattern and software is encoded in a type but it's usually a best practice. So monads are one example and answers are another example. You think Python world would benefit more from having a standardized way to do things, standardized pattern always write classes in this way or something. I think that's a strong side of Haskell. So what do you think about this? I'm not sure. I completely get what you said. Sorry? It's a little bit of the same. One of the ideas hidden behind what I talked about is finding common patterns in different stuff and giving them a common interface which is not something we do that often in Python or maybe we do it but it's more organically. Multiple libraries converging to a common similar set of interface rather than one single formalized interface. I like the theme you draw about these generic libraries that provide the general solution and also the means of composition for the specific libraries. I'm wondering do you think there's something in Haskell that makes that more natural to do or easy to do? Are there like language features of Python that we should be using more or less in order to make that happen? As I said, I think the compiler telling you right away if you have the right interface helps but I think it's also a big part because of the mindset of well that's how people do it. The tools help sure but it's also the community and the way to do it. Any more questions? When do you use Python for what problems Haskell? That's a good question. Most of my projects nowadays because I don't work either with Python or Haskell, most of my projects are personal projects though. It's more take one technology and build something on it. I tend to alternate. Still I always use Python for small little things I need done in half an hour and nowadays I try to use Haskell to build bigger projects I think will get bigger because the way it works kind of helps to make something small then turn it into something bigger. Do you ever have the feeling that the best practice in Python to be Pythonic is holding the Python community back at looking into other communities for solutions for common problems that all programming languages and communities have? In Python there's this notion of code being Pythonic. Good Python code is Pythonic. What do people say? Is this wish to have a Pythonic solution holding us back in terms of looking for solutions in other languages that we can import back to Python? I don't know. You have two meanings to Pythonic. You have a low level Pythonic, single line Pythonic and you have a higher level. It's all solutions, architecture of solution Pythonic. And I guess no, you can find the language solution that we would call Pythonic, elegant structures and solutions to problem. So maybe the fact that the name is Pythonic prevents us in some way to look out. No, I think you can find the solution in another language and find it just as Pythonic as if it was written in Python. One more quick question. Welcome from me. Did you like the talk?
talk to you about some of the ideas I discovered. is interesting to us today is Askel the ecosystem, the community, and the kind of design space. The idea of design space is the is very present in the Haskell community is that library, we try to compare as much as possible it's kind of trying to explore some new parts of you have multiple attempts to solve the packaging the function from the other library, and I'm parsers built on the same principle. You'll find libraries you can use with each of the ways to would like to show in our exploration of that different people and can be found in a different principle. This is the best Haskell library for from Python because the Python library is an that we don't usually explore in Python is generic libraries that provide the general tools help sure but it's also the community and problems that all programming languages and