<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom"><title>The Diligent Developer</title><link href="https://www.thediligentdeveloper.com/" rel="alternate"></link><link href="https://www.thediligentdeveloper.com/feeds/all.atom.xml" rel="self"></link><id>https://www.thediligentdeveloper.com/</id><updated>2024-11-19T10:51:50+01:00</updated><entry><title>The Diligent Developer Framework</title><link href="https://www.thediligentdeveloper.com/framework.html" rel="alternate"></link><published>2024-01-31T00:00:00+01:00</published><updated>2024-11-19T10:51:50+01:00</updated><author><name>Víctor López Ferrando</name></author><id>tag:www.thediligentdeveloper.com,2024-01-31:/framework.html</id><summary type="html">&lt;p&gt;What makes a great programmer, and how can you become one?
This is an important question that many authors have tried to answer.&lt;/p&gt;
&lt;p&gt;On one hand, we have great books like &lt;a href="https://pragprog.com/titles/tpp20/the-pragmatic-programmer-20th-anniversary-edition/"&gt;The Pragmatic Programmer&lt;/a&gt;, or &lt;a href="https://www.amazon.com/Philosophy-Software-Design-John-Ousterhout/dp/1732102201"&gt;A Philosophy of Software Design&lt;/a&gt;, which address this question heads on.
They will make an …&lt;/p&gt;</summary><content type="html">&lt;p&gt;What makes a great programmer, and how can you become one?
This is an important question that many authors have tried to answer.&lt;/p&gt;
&lt;p&gt;On one hand, we have great books like &lt;a href="https://pragprog.com/titles/tpp20/the-pragmatic-programmer-20th-anniversary-edition/"&gt;The Pragmatic Programmer&lt;/a&gt;, or &lt;a href="https://www.amazon.com/Philosophy-Software-Design-John-Ousterhout/dp/1732102201"&gt;A Philosophy of Software Design&lt;/a&gt;, which address this question heads on.
They will make an experienced software developer nod in agreement from cover to cover,
but they won't resonate as much with a junior developer.&lt;/p&gt;
&lt;p&gt;On the other hand, there is no shortage of courses and tutorials on specific programming languages and frameworks.
But after following some of these tutorials, you may still find that something is missing and be lost on how to continue improving.&lt;/p&gt;
&lt;p&gt;The Diligent Developer framework is an attempt to provide practical guidelines to assess and improve your skills to become a better programmer.&lt;/p&gt;
&lt;h2&gt;The 6 skills&lt;/h2&gt;
&lt;p&gt;I have divided the skills that a developer should master into 6 categories:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Coding &amp;amp; problem-solving&lt;/li&gt;
&lt;li&gt;System design and architecture&lt;/li&gt;
&lt;li&gt;Programming language&lt;/li&gt;
&lt;li&gt;Third-party components&lt;/li&gt;
&lt;li&gt;Communication&lt;/li&gt;
&lt;li&gt;Environment&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Before going deeper on what each of these skills mean, let me explain the reasoning behind this list.
The list is &lt;strong&gt;comprehensive&lt;/strong&gt; and &lt;strong&gt;orthogonal&lt;/strong&gt;: mastering all 6 skills will make you a great programmer, but being good at any of these skills doesn't automatically make you good at the others.&lt;/p&gt;
&lt;p&gt;I have seen great problem solvers limited by their lack of understanding of the programming language they where using, I've seen proficient programmers unable to use a relational database to their advantage.
It's common for great developers overall to end up working on the wrong problem due to some miscommunication with managers or colleagues.&lt;/p&gt;
&lt;p&gt;&lt;svg id="radar-chart" style="margin-top: 30px; padding: 30px 0;"&gt;&lt;/svg&gt;&lt;/p&gt;
&lt;p&gt;Let's go deeper on each of these skills.&lt;/p&gt;
&lt;h2&gt;1. Coding &amp;amp; problem-solving&lt;/h2&gt;
&lt;p&gt;Coding is the translation of your thoughts into code, and the related tasks that that requires.
It includes writing new code, fixing a compilation error, debugging an issue, writing a
unit test.
Coding is what you do with a problem that you can fit in your head, when you focus on a specific task.&lt;/p&gt;
&lt;p&gt;Some people may think that coding is not that important, that it is
the kind of thing junior developers do, while senior ones focus on
system architecture and other high-level topics.&lt;/p&gt;
&lt;p&gt;Quite the opposite, you need to be a great coder in order to become a great software engineer,
and framing coding and architecture as competing skills is completely misguided.
There are plenty of great coders that have lead big projects and organizations without compromising on their coding skills, e.g. Peter Norvig, George Hotz or DHH.&lt;/p&gt;
&lt;p&gt;Others might argue the opposite, that coding is all there is to software development, and the rest is just fluff.
This may be the case for extremely talented developers who take for granted a bunch of other skills, but rarely constitutes a good piece of advice for the rest of us.&lt;/p&gt;
&lt;p&gt;The best way to become a better coder is to deliberately practice on problems of the right difficulty: neither too hard nor too easy.
I find the &lt;a href="/why-solving-the-advent-of-code-is-a-great-exercise.html"&gt;Advent of Code&lt;/a&gt; to be a great exercise, but to make the most of it, you need to become aware of your process.
Iterate on your code to make it as simple as possible,
think about what took you so long, why a given bug was difficult to debug,
why some program you wrote worked flawlessly and another required a lot of back and forth,
and compare your solution with others.&lt;/p&gt;
&lt;p&gt;The good thing about improving your coding and problem-solving skills is that solutions that you come up with will be simpler, which will make those problems more manageable, and will
allow you to tackle bigger problems.&lt;/p&gt;
&lt;h2&gt;2. System design and architecture&lt;/h2&gt;
&lt;p&gt;Coding and problem-solving can only get you so far.
Eventually, you will face a problem that doesn't fit in your head, and you will need to break it down into smaller problems.&lt;/p&gt;
&lt;p&gt;At a small scale, this is what you do when you write a function or a class and choose its parameters, attributes, and the way they interact.&lt;/p&gt;
&lt;p&gt;At larger scales, you need to think about larger components, how they are implemented, how they communicate, how they are deployed, how they are monitored, by whom they are developed.&lt;/p&gt;
&lt;p&gt;A bad design introduces unnecessary complexity and can have all kinds of deleterious effects: it can affect performance by adding bottlenecks, make the system error-prone by making it difficult to test, slow development by making the setup of the development environment difficult.&lt;/p&gt;
&lt;p&gt;We developers have a tendency to tackle imaginary problems.
When thinking about software architecture, we tend to think about the future: scalability, high availability, teams of developers.&lt;/p&gt;
&lt;p&gt;However, a good architecture should be as simple as possible to get the job done, and should leave room for future changes.&lt;/p&gt;
&lt;p&gt;To become a better system designer, there are two things you need to do.
First, you need to think deeply of the implications of your design decisions.
When there is a bug, an outage, when a developer is blocked, you need to think hard about how your design contributed to that outcome.&lt;/p&gt;
&lt;p&gt;Second, you need to learn from others' experience.
Blog posts are best in my opinion.
Read why someone thinks microservices are stupid, and how someone runs a company on 3,000 microservices,
how someone deploys 10 times a day to production, why someone stopped using X because it was unreliable.
With time, you will start to see patterns, and you will be able to make better decisions.&lt;/p&gt;
&lt;h2&gt;3. Programming language&lt;/h2&gt;
&lt;p&gt;Whenever you are coding, you are using a programming language.
And which one you use is a big deal.&lt;/p&gt;
&lt;p&gt;An argument could be made that it's not important which programming language you use.
Twitter was built on Ruby, Instagram on Python, WhatsApp on Erlang, so... does it really matter what programming language you use?
It seems you can accomplish mostly anything with any programming language. Why not just pick one and be done with it?&lt;/p&gt;
&lt;p&gt;The truth is that the programming language you use does matter.
WhatsApp chose Erlang because it's designed to be fault-tolerant and distributed,
Twitter and Instagram were built on Ruby on Rails and Django, the web frameworks that revolutionized
web development in the late 2000s.&lt;/p&gt;
&lt;p&gt;A programming language is not only its syntax, it's the ecosystem and the community.
It's the libraries, the frameworks, the tools, the conventions.
As stated almost 20 years ago by Paul Graham in &lt;a href="http://www.paulgraham.com/pypar.html"&gt;The Python Paradox&lt;/a&gt;, a programming language should get you excited by itself.&lt;/p&gt;
&lt;p&gt;There are two paths to improve on this skill:
learn more about the programming language you are using, and learn more programming languages.&lt;/p&gt;
&lt;p&gt;It's difficult to overstate how deep you can go into a programming language.
Mastering Python, JavaScript, Java, or any other language, is a life-long journey.
You may start learning the syntax, then there's the standard library and third party libraries.
You can go a long way with just this knowledge.
But then there are the conventions, the right way to do things, the idioms, the advanced features: concurrency, generics, metaprogramming; and then there's the internals: the implementation of the language, the compiler, the virtual machine, the garbage collector.&lt;/p&gt;
&lt;p&gt;Some developers are deeply bonded to one programming language.
They learned to code with it, grew to think in that language, and it makes them very productive.
Sometimes, this attachment is not so healthy, and thinking of trying new languages
fosters fears of being unproductive, feeling dumb, or wasting time.&lt;/p&gt;
&lt;p&gt;It's important not to confuse learning a programming language with learning to program, which generally go hand in hand the first time.
Most of the coding skill is transferable from one language to another, and
learning new programming paradigms can be a low-hanging fruit for improving your craft.&lt;/p&gt;
&lt;h2&gt;4. Third-party components&lt;/h2&gt;
&lt;p&gt;We love to code, but we can't code everything (&lt;a href="https://www.youtube.com/c/andreaskling"&gt;there are some exceptions&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;Databases, caches or message queues, and libraries that implement encryption, compression, graphics are clear contenders for not being coded from scratch.&lt;/p&gt;
&lt;p&gt;Knowing how to use a relational database or a message queue is hugely beneficial for you as a developer.
For one, it removes a ton of responsibility from you.
In a hundred years, I couldn't develop an equivalent of PostgreSQL, so it is great that it exists and I can use it for free.&lt;/p&gt;
&lt;p&gt;Apart from filling a concrete need in our system, third-party components bring other benefits.
Being exposed to great tools that solve difficult problems also serves as an example to follow in your own coding.
This is specially true for open source tools.&lt;/p&gt;
&lt;p&gt;Good and sane decisions in naming, API design, backwards-compatibility, etc. can serve as an inspiration for your own work.&lt;/p&gt;
&lt;p&gt;But there's a world of difference between knowing that a tool exists, and knowing how to use it.
Phrases like "just put a cache in front of that service" or "just store it in a database" are often thrown around, but properly implementing them is much harder.&lt;/p&gt;
&lt;p&gt;Even though each tool is different, I've also found that learning how to use them is also a transferable skill.
Learning to test and benchmark different configurations, navigating the documentation, finding help online, prototyping before going all in are things that you can practice.&lt;/p&gt;
&lt;p&gt;Similar to third-party components, we have services.
Sentry, Datadog, AWS, Mailgun, Stripe are undoubtedly useful services, but they are also black boxes.
They come with great benefits, but the skill of using them is not that transferable and doesn't contribute as much to making you a better developer.&lt;/p&gt;
&lt;p&gt;If you are used to relying on managed databases or clouds, I suggest you install some of those components locally, and play around with them. Redis, PostgreSQL, ClickHouse, SQLite, NATS are all great and inspiring projects.&lt;/p&gt;
&lt;h2&gt;5. Communication&lt;/h2&gt;
&lt;p&gt;When you code, you are communicating with the machine, but you are also communicating with other developers.
You communicate through your code, with your choice of names for variables, functions, classes, and also through your comments.&lt;/p&gt;
&lt;p&gt;Apart from the code, you also communicate through commit messages, bug reports, issue comments, instant messages and emails.
And beyond written communication, you surely have conversations, meetings or presentations.&lt;/p&gt;
&lt;p&gt;Being effective at these forms of communication is crucial to be a good developer.
It's not uncommon for great developers to be outstanding &lt;a href="https://blog.codinghorror.com/"&gt;bloggers&lt;/a&gt;, &lt;a href="http://antirez.com"&gt;science fiction writers&lt;/a&gt; or &lt;a href="https://twitter.com/dhh"&gt;best-selling authors&lt;/a&gt;.
Counter to popular belief, good programming skills correlate more with good communication skills than with math talent (see &lt;a href="https://www.manning.com/books/the-programmers-brain"&gt;The Programmer's Brain&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;A crucial side effect of improving your communication skills is that of improving your thinking.
Has it ever happened to you that in the process of writing a detailed StackOverflow question or a question to some colleague you found the solution to the issue yourself?
It's not a coincidence.
By making the effort to explain the issue to someone else, you are forced to get a clearer understanding of the problem, and this often leads to the solution.&lt;/p&gt;
&lt;p&gt;Similarly, by splitting each commit message into logical chunks, with a description of the changes introduced, you can get a better understanding of what you are doing, and you can also help your colleagues understand your code.&lt;/p&gt;
&lt;p&gt;Practice is crucial to become a better communicator, and there's a lot you can do.
Trying to write the perfect email, documentation page or commit message can be blocking and frustrating.
It's better to practice and try to improve gradually, getting out of your comfort zone bit by bit.
Explain the last bug you fixed to your hairdresser, write a blog post about this thought you had, spend 2 more minutes on that commit message.&lt;/p&gt;
&lt;p&gt;Communication plays a central role in your work as a software engineer and it requires you to be conscientious just like for any other skill.&lt;/p&gt;
&lt;h2&gt;6. Environment&lt;/h2&gt;
&lt;p&gt;Programming is one of the most purely intellectual activities you can do, but it doesn't happen in a void.
Mastering the tools around your craft can greatly improve your productivity.&lt;/p&gt;
&lt;p&gt;This environment includes your code editor or IDE, the debugger, shell, version control software, password manager, to-do app, operating system and any other tool you use to get your job done.
It also includes your physical setting: keyboard, mouse, screen, desk, chair, and the room you are in.
You could even fit your diet, exercise and sleep habits in this category if you wish.&lt;/p&gt;
&lt;p&gt;All of these things can make a big difference in your productivity, specially for the worse.
You will not get a huge productivity boost by upgrading your keyboard or getting a comfortable chair, but you will get a huge productivity hit if you develop &lt;a href="https://en.wikipedia.org/wiki/Repetitive_strain_injury"&gt;RSI&lt;/a&gt; or back pain.&lt;/p&gt;
&lt;p&gt;Tweaking and improving your environment is the topic on this framework that is more prone to fetishization.
It can be exciting to build your own keyboards and learn a new layout every 3 months, but you must not kid yourself into thinking that this will make you a better developer.&lt;/p&gt;
&lt;p&gt;Still, there are some things that are worth investing time in.
Same as with coding, you need to be aware of your process and realize when your environment is the bottleneck.&lt;/p&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;We developers take hundreds or thousands of decisions every day, big or small.
I hope this framework allows you to zoom out and think of your craft as a whole, hopefully providing some guidance in your journey.&lt;/p&gt;
&lt;h1&gt;Where to go from here&lt;/h1&gt;
&lt;p&gt;I write a &lt;strong&gt;newsletter&lt;/strong&gt; in which I share my thoughts on software development, productivity, entrepreneurship and more.
Subscribe below if you want to receive it.
&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;script src="https://cdn.jsdelivr.net/npm/chart.xkcd@1/dist/chart.xkcd.min.js"&gt;&lt;/script&gt;
&lt;script&gt;
const svg = document.getElementById('radar-chart');
new chartXkcd.Radar(svg, {
title: "The Diligent Developer Framework Skills",
data: {
labels: ['1. Coding', '2. Architecture', '3. Language', '4. Components', '5. Communication', '6. Environment'],
datasets: [{
data: [3, 2, 2, 2, 1, 2],
}],
},
options: { // optional
dotSize: .8,
showLabels: true,
legendPosition: chartXkcd.config.positionType.upRight,
},
});
// Remove filter attributes to avoid blurring
document.querySelector('.xkcd-chart-radar-grid').removeAttribute('filter');
document.querySelector('.xkcd-chart-radar-group').removeAttribute('filter');
// Remove axis ticks
document.querySelectorAll('.xkcd-chart-radar-tick').forEach((tick) =&gt; tick.remove());
// Add separation to title
document.querySelector('#radar-chart &gt; text').setAttribute('y', '15');
// If screen size is small, set font size to 14
if (window.innerWidth &lt; 600) {
document.querySelectorAll('#radar-chart &gt; text').forEach((label) =&gt; { console.log(label); label.setAttribute('style',  'font-size: 16px') });
document.querySelectorAll('#radar-chart text.xkcd-chart-radar-label').forEach((label) =&gt; { console.log(label); label.setAttribute('style',  'font-size: 14px') });
}
&lt;/script&gt;</content><category term="articles"></category></entry><entry><title>Nothing changing is a change in itself</title><link href="https://www.thediligentdeveloper.com/nothing-changing-is-a-change-in-itself.html" rel="alternate"></link><published>2023-12-13T00:00:00+01:00</published><updated>2024-11-19T10:51:50+01:00</updated><author><name>Víctor López Ferrando</name></author><id>tag:www.thediligentdeveloper.com,2023-12-13:/nothing-changing-is-a-change-in-itself.html</id><summary type="html">&lt;p&gt;I'm in a video call with 15 other software engineers, managers, devops.
Two of them are from my company, the rest are from the client and their systems integrator.&lt;/p&gt;
&lt;p&gt;The system has been &lt;strong&gt;down for 3 days&lt;/strong&gt;, and they are not happy.
Tens of thousands of dollars are lost every …&lt;/p&gt;</summary><content type="html">&lt;p&gt;I'm in a video call with 15 other software engineers, managers, devops.
Two of them are from my company, the rest are from the client and their systems integrator.&lt;/p&gt;
&lt;p&gt;The system has been &lt;strong&gt;down for 3 days&lt;/strong&gt;, and they are not happy.
Tens of thousands of dollars are lost every day of downtime.&lt;/p&gt;
&lt;p&gt;They pinged us 3 days ago saying there was some issue, and after checking our monitoring we responded with an &lt;em&gt;everything looks fine on our side&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;During the following days the issue escalated more and more, and their conclusion was that &lt;strong&gt;it &lt;em&gt;was&lt;/em&gt; our fault&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Their thinking was simple: we haven't changed anything in 1 month, no new code, no new deployments.
Therefore, it must be someone else's fault.&lt;/p&gt;
&lt;p&gt;I am still pretty sure that our systems are working fine, but it is difficult to get out of the situation.
I ask for proof.
Have you added some debug messages that show that the request is being sent, but no response is being received?
That is in my mind the simplest way to see where the program gets hanged.&lt;/p&gt;
&lt;p&gt;Their answer is that this is not even necessary, because this is a proxy microservice that &lt;em&gt;only&lt;/em&gt; calls our service and then returns.
Now that, to me, is a &lt;strong&gt;red flag&lt;/strong&gt;.
In three days of outage, the least you could do is confirm your suspicion of where the problem is; specially if it takes 5 minutes to confirm, before pulling 15 people into a meeting.&lt;/p&gt;
&lt;p&gt;I still don't believe the problem is ours, so I ask to see the code.
My hope is to find out that their proxy microservice is in fact doing something else, and that is what times out.&lt;/p&gt;
&lt;p&gt;They screen-share the code.
It turns out it actually is very simple: a TypeScript implementation of a gRPC API which forwarded all requests to our remote server.
Nothing else.&lt;/p&gt;
&lt;p&gt;And as the client's VP stresses once and again, &lt;em&gt;they haven't changed the service for 1.5 months, so it can't be their fault&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;That finally gets me thinking... 1.5 months? The project started a few months ago, and I bet this is the &lt;em&gt;longest time the service had been running without a restart&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Now, there is a reason why restarting the service might help.
This is a microservice that acts as a proxy, and I know gRPC and JavaScript don't work extremely well together, it is not one of the best supported languages. After running for a long time, processing millions of requests, some answered, some timed out, some streaming that may never be closed, etc. it may happen that some buffer got filled up somewhere or the list of open connections grew too large or something, and then the service stops answering any request.&lt;/p&gt;
&lt;p&gt;The bad thing is that it would look like the problem is that the external service is not answering, the good thing is that a simple restart would fix the issue.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Have you tried to restart the service?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="images/have-you-tried-turning-it-off-and-on-again.webp" style="margin: 3em 0"&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;No&lt;/em&gt;. They restart the service immediately, and &lt;strong&gt;everything is working again&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;I cheered, but not everyone was as happy as me.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;Now this is not only a funny story, but there are some things we can learn.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;When you face a bug or an incident, it is important to &lt;strong&gt;explore by your own means as much as you can&lt;/strong&gt; what the issue may be. In this case: they could have just restarted the service and added debug messages. Adding other people in the loop always adds delays, and you should only do it when you are blocked or it takes a huge amount of time to proceed by yourself.&lt;/li&gt;
&lt;li&gt;Be careful with microservices architectures in large environments. One of the reasons why the service wasn't restarted is that the &lt;strong&gt;developer didn't have access to a restart button&lt;/strong&gt;. They need to contact the devops team in order to get a restart, or a new deployment going. This makes sense to some extent, but it can add too much friction to just debug the simplest of issues.&lt;/li&gt;
&lt;li&gt;Be &lt;strong&gt;careful with simple and stupid microservices&lt;/strong&gt;. We need to call an external API? Let's add a simple API proxy microservice. There may be reasons to do this, but in 99% of the cases I would suggest you use a &lt;strong&gt;library&lt;/strong&gt; for this, and not a microservice. The code may look so simple that you think it is completely robust. But running a separate microservice for this adds a bunch of complexity: more network hops, separate logs, a single bottleneck for all other microservices using the API. So you should provide a real benefit to you application in exchange of all this addeed complexity, and a dumb API proxy doesn't.&lt;/li&gt;
&lt;/ol&gt;</content><category term="articles"></category></entry><entry><title>Spaced repetition really works</title><link href="https://www.thediligentdeveloper.com/spaced-repetition-really-works.html" rel="alternate"></link><published>2023-09-13T00:00:00+02:00</published><updated>2024-11-19T10:51:50+01:00</updated><author><name>Víctor López Ferrando</name></author><id>tag:www.thediligentdeveloper.com,2023-09-13:/spaced-repetition-really-works.html</id><summary type="html">&lt;p&gt;Spaced repetition is the practice of learning with flashcards reviewed at increasingly longer intervals.&lt;/p&gt;
&lt;p&gt;The logic behind it is that when you are first exposed to a piece of information, you are prone to forget it quickly, but revisiting it you will remember it for longer periods, and thus it's …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Spaced repetition is the practice of learning with flashcards reviewed at increasingly longer intervals.&lt;/p&gt;
&lt;p&gt;The logic behind it is that when you are first exposed to a piece of information, you are prone to forget it quickly, but revisiting it you will remember it for longer periods, and thus it's not necessary to review it as often.&lt;/p&gt;
&lt;p&gt;This approach is widely used to learn new languages, and multiple scientific studies have proven it to be extremely effective.&lt;/p&gt;
&lt;p&gt;This is all cool, but I was a bit of a &lt;strong&gt;skeptic&lt;/strong&gt;. The reason is that people learning with &lt;a href="https://apps.ankiweb.net/"&gt;Anki&lt;/a&gt; were generally extremely motivated and were spending a lot of time creating their decks, and these are the kind of people who are good at learning, with or without spaced repetition.&lt;/p&gt;
&lt;p&gt;I needed proof, subjective proof, and I found it.&lt;/p&gt;
&lt;p&gt;Last year, my friend Maria wanted to get her Spanish nationality, for which she had to take a test. The test has a pool of 300 questions from which 30 are chosen, and you are only allowed 3 mistakes. Some questions are extremely easy, but others are difficult even for a Spaniard. They ask about some facts such as who wrote some book, or what is someone known for.&lt;/p&gt;
&lt;p&gt;The exam was due in one month, and Maria was pretty scared. She had been studying for weeks, but there were some questions she kept getting wrong, and it was hard to go through the whole list of 300 questions, names got mixed in her head.&lt;/p&gt;
&lt;p&gt;I suggested giving spaced repetition a try.&lt;/p&gt;
&lt;p&gt;I extracted a CSV from the PDF, and created an Anki deck which I later loaded on her phone with &lt;a href="https://play.google.com/store/apps/details?id=com.ichi2.anki"&gt;AnkiDroid&lt;/a&gt;, and she started reviewing the deck on her phone, going through the questions on her spare time.&lt;/p&gt;
&lt;p&gt;The result was &lt;strong&gt;incredible&lt;/strong&gt;. Of course, she aced the test. But not only that, in one or two weeks all her fear had faded. She was learning the whole deck, and &lt;em&gt;she knew it&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;This experience proved two things to me:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Spaced repetition &lt;em&gt;works&lt;/em&gt;. The science is right.&lt;/li&gt;
&lt;li&gt;You don't need to create your own decks. As long as cards are atomic, have the right context and are shown in the right order, there is no extra effort a learner needs to do.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This was my &lt;em&gt;aha moment&lt;/em&gt;, and that's when I registered the domain &lt;a href="https://python.cards"&gt;python.cards&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Not all programmers realize how beneficial it is to &lt;em&gt;know&lt;/em&gt; their language better. It's not only about coding faster or saving some Google searches, it's about boosting your confidence and having a solid understanding of your tool. It's about reaching higher levels of proficiency.&lt;/p&gt;
&lt;p&gt;Experienced programmers master their language by being exposed to it for years, but there is a shortcut: &lt;strong&gt;spaced repetition&lt;/strong&gt;.&lt;/p&gt;</content><category term="articles"></category></entry><entry><title>Why solving the Advent of Code is a great exercise</title><link href="https://www.thediligentdeveloper.com/why-solving-the-advent-of-code-is-a-great-exercise.html" rel="alternate"></link><published>2023-08-22T00:00:00+02:00</published><updated>2024-11-19T10:51:50+01:00</updated><author><name>Víctor López Ferrando</name></author><id>tag:www.thediligentdeveloper.com,2023-08-22:/why-solving-the-advent-of-code-is-a-great-exercise.html</id><summary type="html">&lt;p&gt;The &lt;a href="https://adventofcode.com/"&gt;Advent of Code&lt;/a&gt; is a yearly challenge that consists of 25 programming problems, one each day, from December 1st to December 25th.
Hundreds of thousands of programmers participate each year, and use it as a way to improve their coding skills, learn new programming languages or just for fun …&lt;/p&gt;</summary><content type="html">&lt;p&gt;The &lt;a href="https://adventofcode.com/"&gt;Advent of Code&lt;/a&gt; is a yearly challenge that consists of 25 programming problems, one each day, from December 1st to December 25th.
Hundreds of thousands of programmers participate each year, and use it as a way to improve their coding skills, learn new programming languages or just for fun.&lt;/p&gt;
&lt;p&gt;I participated for the first time in 2020, having programmed in Python for almost a decade.
I solved all the problems on the day they were published, didn't have excessive trouble with any of them, had fun, and went on with my life.&lt;/p&gt;
&lt;p&gt;Three or four months later, I came across the &lt;a href="https://github.com/norvig/pytudes"&gt;Pytudes repository&lt;/a&gt; by Peter Norvig and &lt;strong&gt;my mind was blown&lt;/strong&gt;. In case you don't know him (I didn't at the time), he is a legend in the programming world and has been the director of Google Research for many years, among other things.&lt;/p&gt;
&lt;p&gt;The point is his solutions are brief, elegant, and use a ton of Python features that I didn't know about.&lt;/p&gt;
&lt;p&gt;I was so baffled that I revisited all the problems, and worked on them, one by one, trying to understand his approach, and the Python features he used, and identifying the gaps in my knowledge that prevented me from solving the problems in a similar way.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;What does Peter Norvig know, that I don't, that prevents me from writing a solution like his?&lt;/p&gt;
&lt;p&gt;&amp;mdash; &lt;cite&gt;me&lt;/cite&gt;, on loop on my head&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This was an inflection point for me. At the end of 2021, I participated again in the Advent of Code, but this time I focused not on solving the problems, but on &lt;em&gt;how&lt;/em&gt; I solved them. I ran a small competition with a friend, trying to see who found the most elegant solution for each problem.&lt;/p&gt;
&lt;p&gt;I'm not exactly proud of the outcome, it landed on the "hackish" side more than on the "elegant" side. E.g., for &lt;a href="https://adventofcode.com/2021/day/8"&gt;day 8&lt;/a&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;digits&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;abcefg cf acdeg acdfg bcdf abdfg abdefg acf abcdefg abcdfg&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;translate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;maketrans&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;zip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;abcdefg&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;))))&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;split&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="n"&gt;fsfs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;frozenset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;frozenset&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="n"&gt;PERMS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;fsfs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;digits&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;)):&lt;/span&gt; &lt;span class="n"&gt;mapt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;set&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;digits&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;permutations&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;abcdefg&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;
&lt;span class="n"&gt;nums&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;ds&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;qs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;PERMS&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;fsfs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ds&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;q&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;qs&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;in8&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;atoms&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;day8_1&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;rows&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;nums&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;[:&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="p"&gt;:]))&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;day8_2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;rows&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;enumerate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nums&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;[:&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="p"&gt;:])))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Anyway, by this time, whenever I read a Python code I had written more than a year ago, I would immediately spot things that could be improved and that I would not do in the same way.
&lt;strong&gt;It feels great to see how much you improved over time&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;For the 2022 edition, I went one step further and recorded myself solving some of the problems, and &lt;a href="https://www.youtube.com/watch?v=war1DKS2QZE&amp;amp;list=PL4R7dYNzbaX0MI2HyM2IOly83f5i5EZNr"&gt;uploaded the videos to YouTube&lt;/a&gt;. This also proved to be a great exercise, because it made me focus 100% on the problem I was solving, and also because I had to be deliberate about what I was doing.&lt;/p&gt;
&lt;iframe width="560" height="315" src="https://www.youtube.com/embed/5pD2x8rB1MI?si=yYuM4thq3Tvl-0f-" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen style="margin-top: 40px; margin-bottom: 40px"&gt;&lt;/iframe&gt;

&lt;p&gt;In case you are curious, you can check my code at &lt;a href="https://github.com/vlopezferrando/advent-of-code"&gt;this repository on GitHub&lt;/a&gt;, which has all my solutions and can judge for yourself how good or bad they are.&lt;/p&gt;
&lt;h2&gt;Mentoring with the Advent of Code&lt;/h2&gt;
&lt;p&gt;I've been mentoring a few developers over the last year, helping them &lt;strong&gt;improve their coding and software design skills&lt;/strong&gt;.
I have found that the Advent of Code problems are a great subject of study, even more than the typical Leetcode problems.&lt;/p&gt;
&lt;p&gt;Approaching the problems deliberately, trying to find the "best" solution, and not just "a" solution, is a great exercise. When you have given your best, it is the best time to come in and give you feedback on how to improve: how to simplify the algorithm, make better use of the language features, improve the readability, etc.&lt;/p&gt;</content><category term="articles"></category></entry><entry><title>My collection of scientific and technical books</title><link href="https://www.thediligentdeveloper.com/scientific-technical-books.html" rel="alternate"></link><published>2018-12-16T12:00:00+01:00</published><updated>2024-11-19T10:51:50+01:00</updated><author><name>Víctor López Ferrando</name></author><id>tag:www.thediligentdeveloper.com,2018-12-16:/scientific-technical-books.html</id><summary type="html">&lt;p&gt;&lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2018-scientific-tehcnical-books/llibres.gif" class="u-pull-right" width="200px" style="max-width: 40%; margin-left: 20px"&gt;&lt;/p&gt;
&lt;p&gt;What technical books would you buy if you had $1000 to spend? This is the question I asked myself when I learned that my Ph.D. scholarship included some money destined to buy material that I had not spent. After a few days of research, I selected a list of …&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2018-scientific-tehcnical-books/llibres.gif" class="u-pull-right" width="200px" style="max-width: 40%; margin-left: 20px"&gt;&lt;/p&gt;
&lt;p&gt;What technical books would you buy if you had $1000 to spend? This is the question I asked myself when I learned that my Ph.D. scholarship included some money destined to buy material that I had not spent. After a few days of research, I selected a list of more than 30 books.&lt;/p&gt;
&lt;p&gt;It's been a few months now, and I've had time to read some of the books and leaf through the rest. Here you have my selection, with a brief comment on each book.&lt;/p&gt;
&lt;hr class="no-border u-cf"&gt;
&lt;p&gt;&lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2018-scientific-tehcnical-books/BioinformaticsAlgorithms.jpg" class="u-pull-right" width="200px" style="max-width: 40%; margin-left: 20px"&gt;&lt;/p&gt;
&lt;h3&gt;Bioinformatics algorithms&lt;/h3&gt;
&lt;p&gt;A wonderful book, which has just come out in its &lt;a href="http://bioinformaticsalgorithms.com/"&gt;third edition&lt;/a&gt;. It explains in a didactic
and entertaining way the fundamental algorithms of different
bioinformatics fields. The book, available at my university's library, helped me in preparing the &lt;a href="https://bioinf.me/en/contest/2018"&gt;Bioinformatics contest 2018&lt;/a&gt;, and was an indispensable acquisition.&lt;/p&gt;
&lt;hr class="no-border u-cf"&gt;
&lt;p&gt;&lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2018-scientific-tehcnical-books/Physics.jpeg" class="u-pull-right" width="200px" style="max-width: 40%; margin-left: 20px"&gt;&lt;/p&gt;
&lt;h3&gt;Physics for Scientists and Engineers&lt;/h3&gt;
&lt;p&gt;The classic book of physics, with chapters devoted to mechanics, thermodynamics, electromagnetism, relativity... I have always liked physics, and in high school I tried to learn as much as I could. This book will help me refresh and come back, from time to time, to whatever matters I may be interested on.&lt;/p&gt;
&lt;hr class="no-border u-cf"&gt;
&lt;p&gt;&lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2018-scientific-tehcnical-books/Calculus.jpg" class="u-pull-right" width="200px" style="max-width: 40%; margin-left: 20px"&gt;&lt;/p&gt;
&lt;h3&gt;Calculus&lt;/h3&gt;
&lt;p&gt;I have often commented with some friends from university that we should have paid more attention to the courses’ bibliography in college. Studying based on books would have allowed us to return years later to those same books, which will always be better than the notes we might have taken. This book is the first step to correct that mistake.&lt;/p&gt;
&lt;hr class="no-border u-cf"&gt;
&lt;p&gt;&lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2018-scientific-tehcnical-books/IntroductionToAlgorithms.jpeg" class="u-pull-right" width="200px" style="max-width: 40%; margin-left: 20px"&gt;&lt;/p&gt;
&lt;h3&gt;Introduction to algorithms&lt;/h3&gt;
&lt;p&gt;The bible of algorithmics. A book that I consulted extensively to prepare programming competitions during my university years, which is much more than an &lt;em&gt;introduction&lt;/em&gt; to algorithms and data structures.&lt;/p&gt;
&lt;hr class="no-border u-cf"&gt;
&lt;p&gt;&lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2018-scientific-tehcnical-books/UnderstandingMachineLearning.jpg" class="u-pull-right" width="200px" style="max-width: 40%; margin-left: 20px"&gt;&lt;/p&gt;
&lt;h3&gt;Understanding machine learning&lt;/h3&gt;
&lt;p&gt;This book is an introduction to the theoretical foundations of machine learning. A very well explained book that has been useful to me to understand some methods I have used in my thesis.&lt;/p&gt;
&lt;hr class="no-border u-cf"&gt;
&lt;p&gt;&lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2018-scientific-tehcnical-books/Molecular.jpg" class="u-pull-right" width="200px" style="max-width: 40%; margin-left: 20px"&gt;&lt;/p&gt;
&lt;h3&gt;Molecular Biology of the Cell&lt;/h3&gt;
&lt;p&gt;Although I am almost a doctor in biomedicine (bioinformatics more specifically), my knowledge on biology some years ago was rather limited. For me, the first chapters of this book were very useful to get in touch with the matter, and I have used it as a reference book for years.&lt;/p&gt;
&lt;hr class="no-border u-cf"&gt;
&lt;p&gt;&lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2018-scientific-tehcnical-books/Lehninger.jpg" class="u-pull-right" width="200px" style="max-width: 40%; margin-left: 20px"&gt;&lt;/p&gt;
&lt;h3&gt;Principles of biochemistry&lt;/h3&gt;
&lt;p&gt;The bible of biochemistry, a book that has everything I will never need to know about this matter.&lt;/p&gt;
&lt;hr class="no-border u-cf"&gt;
&lt;p&gt;&lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2018-scientific-tehcnical-books/LewinsGenes.jpg" class="u-pull-right" width="200px" style="max-width: 40%; margin-left: 20px"&gt;&lt;/p&gt;
&lt;h3&gt;Lewin's genes XII&lt;/h3&gt;
&lt;p&gt;A book on genetics that I did not know before doing this search. It has good reviews and is a good complement to the previous books on biology and biochemistry.&lt;/p&gt;
&lt;hr class="no-border u-cf"&gt;
&lt;p&gt;&lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2018-scientific-tehcnical-books/C.jpg" class="u-pull-right" width="200px" style="max-width: 40%; margin-left: 20px"&gt;&lt;/p&gt;
&lt;h2&gt;The C Programming Language&lt;/h2&gt;
&lt;p&gt;C is probably the most influential programming language in history. This book, one of whose authors is the creator of C, is the classic manual of this language.&lt;/p&gt;
&lt;hr class="no-border u-cf"&gt;
&lt;p&gt;&lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2018-scientific-tehcnical-books/ExpertC.jpg" class="u-pull-right" width="200px" style="max-width: 40%; margin-left: 20px"&gt;&lt;/p&gt;
&lt;h3&gt;Expert C Programming&lt;/h3&gt;
&lt;p&gt;Although the previous book is the basic reference of C, a lot more is needed to write &lt;em&gt;good&lt;/em&gt; C. This book contains dozens of tricks, good practices, etc. that help us do it better.&lt;/p&gt;
&lt;hr class="no-border u-cf"&gt;
&lt;p&gt;&lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2018-scientific-tehcnical-books/CODE.jpg" class="u-pull-right" width="200px" style="max-width: 40%; margin-left: 20px"&gt;&lt;/p&gt;
&lt;h3&gt;CODE: The Hidden Language of Computer Hardware and Software&lt;/h3&gt;
&lt;p&gt;Interesting and entertaining book that summarizes the history of computer science, of all the advances that have converged in the creation of computers.&lt;/p&gt;
&lt;hr class="no-border u-cf"&gt;
&lt;p&gt;&lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2018-scientific-tehcnical-books/CollectiveIntelligence.jpg" class="u-pull-right" width="200px" style="max-width: 40%; margin-left: 20px"&gt;&lt;/p&gt;
&lt;h3&gt;Programming Collective Intelligence&lt;/h3&gt;
&lt;p&gt;How does Google choose relevant web pages for a given search query? How does Netflix know what movies we might like? How does Facebook know which friends to suggest? This book, which has a peculiar title, deals with the algorithms that have taken great relevance since the rise of the web.&lt;/p&gt;
&lt;hr class="no-border u-cf"&gt;
&lt;p&gt;&lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2018-scientific-tehcnical-books/CompetitiveProgramming3.jpg" class="u-pull-right" width="200px" style="max-width: 40%; margin-left: 20px"&gt;&lt;/p&gt;
&lt;h3&gt;Competitive Programming 3&lt;/h3&gt;
&lt;p&gt;A real gem, how useful it would have been when I was a student! The authors, true masters of programming contests, condense in this book years and years of training, practice and study. In it they deal with all the issues related to programming competitions: algorithms, data structures, implementation tricks, relevant theorems and mathematical properties, and much more.&lt;/p&gt;
&lt;hr class="no-border u-cf"&gt;
&lt;p&gt;&lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2018-scientific-tehcnical-books/ComputerNetworks.jpeg" class="u-pull-right" width="200px" style="max-width: 40%; margin-left: 20px"&gt;&lt;/p&gt;
&lt;h3&gt;Computer Networks&lt;/h3&gt;
&lt;p&gt;The bible of computer networks. The truth is that I did not know this book, but my colleague Pau recommended it to me; he always remembers a lesson from this book: we can not underestimate the bandwidth of a van full of hard drives.&lt;/p&gt;
&lt;hr class="no-border u-cf"&gt;
&lt;p&gt;&lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2018-scientific-tehcnical-books/DeepLearningPython.jpg" class="u-pull-right" width="200px" style="max-width: 40%; margin-left: 20px"&gt;&lt;/p&gt;
&lt;h3&gt;Deep learning with Python&lt;/h3&gt;
&lt;p&gt;Deep learning, that is, machine learning based on neural networks of many layers, has been a revolution in recent years in the world of artificial intelligence. The advances have been so fast, that today it is feasible to use Python to train your models, and you can even do it at home if you buy a good GPU. This book, written by the author of Keras, one of the most popular deep learning frameworks, introduces us to this world, beginning with the theoretical foundation and soon getting hands on practice. It should also be noted that the book is very well written.&lt;/p&gt;
&lt;hr class="no-border u-cf"&gt;
&lt;p&gt;&lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2018-scientific-tehcnical-books/EffectiveCPP.jpg" class="u-pull-right" width="200px" style="max-width: 40%; margin-left: 20px"&gt;&lt;/p&gt;
&lt;h3&gt;Effective C++&lt;/h3&gt;
&lt;p&gt;A book that I have consulted many times in PDF and that I wanted to have. With this book, thousands of programmers have improved their knowledge of C++.&lt;/p&gt;
&lt;hr class="no-border u-cf"&gt;
&lt;p&gt;&lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2018-scientific-tehcnical-books/EffectiveModernCPP.jpg" class="u-pull-right" width="200px" style="max-width: 40%; margin-left: 20px"&gt;&lt;/p&gt;
&lt;h3&gt;Effective Modern C++&lt;/h3&gt;
&lt;p&gt;The necessary complement to the previous book. C++ has introduced major changes in recent years, and Scott Meyers summarizes the best of these new features. Especially interesting are the chapters discussing concurrent programming.&lt;/p&gt;
&lt;hr class="no-border u-cf"&gt;
&lt;p&gt;&lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2018-scientific-tehcnical-books/Go.jpg" class="u-pull-right" width="200px" style="max-width: 40%; margin-left: 20px"&gt;&lt;/p&gt;
&lt;h3&gt;The Go Programming Language&lt;/h3&gt;
&lt;p&gt;Go is a very interesting programming language, which shines in terms of simplicity and concurrence. It is specially designed for projects on which several people work, long codes where conventions need to be followed, and efficiency is important. This book is a complete introduction to the language.&lt;/p&gt;
&lt;hr class="no-border u-cf"&gt;
&lt;p&gt;&lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2018-scientific-tehcnical-books/RTFM.jpg" class="u-pull-right" width="200px" style="max-width: 40%; margin-left: 20px"&gt;&lt;/p&gt;
&lt;h3&gt;RTFM: Red Team Field Manual&lt;/h3&gt;
&lt;p&gt;RTFM (usually Read The Fucking Manual) is what my friend Alberto used to say when I asked him for the &lt;em&gt;nth&lt;/em&gt; time about some option of the &lt;code&gt;grep&lt;/code&gt; command. This book contains a catalog of hundreds of commands from a variety of themes: Windows, *nix, networks, web, tricks... Most of the commands are unknown to me, which makes this very a interesting source of information.&lt;/p&gt;
&lt;hr class="no-border u-cf"&gt;
&lt;p&gt;&lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2018-scientific-tehcnical-books/KungFu.jpg" class="u-pull-right" width="200px" style="max-width: 40%; margin-left: 20px"&gt;&lt;/p&gt;
&lt;h3&gt;Command Line Kung Fu&lt;/h3&gt;
&lt;p&gt;A book which is less advanced than the previous one, but gives us a good base to start working effectively on the command line.&lt;/p&gt;
&lt;hr class="no-border u-cf"&gt;
&lt;p&gt;&lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2018-scientific-tehcnical-books/HitchhickersPython.jpg" class="u-pull-right" width="200px" style="max-width: 40%; margin-left: 20px"&gt;&lt;/p&gt;
&lt;h3&gt;The Hitchhiker's Guide to Python&lt;/h3&gt;
&lt;p&gt;This guide to Python, written by the author of requests and other popular packages, rather than a guide on Python, is a guide on good practices in terms of project management, how to organize the code, manage dependencies, etc. This book may become obsolete in a few years, but it is relevant at the moment.&lt;/p&gt;
&lt;hr class="no-border u-cf"&gt;
&lt;p&gt;&lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2018-scientific-tehcnical-books/JavascriptGoodParts.jpg" class="u-pull-right" width="200px" style="max-width: 40%; margin-left: 20px"&gt;&lt;/p&gt;
&lt;h3&gt;JavasScript: The Good Parts&lt;/h3&gt;
&lt;p&gt;This book, published in 2006, has been very influential in the resurgence of the JavaScript programming language. JavaScript, a language that had very bad reputation for a long time, has become one of the most used languages in recent years. In just 100 pages, the author is able to present the strengths of JavaScript, helping the programmer to avoid common pitfalls, and providing a solid base to build upon.&lt;/p&gt;
&lt;p&gt;During the last years, however, new standards of the language have been released, and it would be great if the author published a new and updated edition of the book.&lt;/p&gt;
&lt;hr class="no-border u-cf"&gt;
&lt;p&gt;&lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2018-scientific-tehcnical-books/LegacyCode.jpg" class="u-pull-right" width="200px" style="max-width: 40%; margin-left: 20px"&gt;&lt;/p&gt;
&lt;h3&gt;Working Effectively with Legacy Code&lt;/h3&gt;
&lt;p&gt;How should we handle old code bases? Fortunately, many people have encountered this situation previously and their experience helps the rest of us to face these challenges. This is one of the most relevant books regarding this topic.&lt;/p&gt;
&lt;hr class="no-border u-cf"&gt;
&lt;p&gt;&lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2018-scientific-tehcnical-books/Refactoring.jpeg" class="u-pull-right" width="200px" style="max-width: 40%; margin-left: 20px"&gt;&lt;/p&gt;
&lt;h3&gt;Refactoring: Improving the Design of Existing Code&lt;/h3&gt;
&lt;p&gt;Refactoring is changing a code for another that does the same, but which is better in some way. This book explores this concept, and offers us dozens of examples and patterns to detect candidate codes to be refactored.&lt;/p&gt;
&lt;p&gt;The book was published almost 20 years ago, and is specially focused on Java and the paradigm of object-oriented programming, however, it has timeless lessons that can be applied to all scenarios. Interestingly, a &lt;a href="https://martinfowler.com/articles/refactoring-2nd-ed.html"&gt;new edition has just been published&lt;/a&gt;
 that changes this approach.&lt;/p&gt;
&lt;hr class="no-border u-cf"&gt;
&lt;p&gt;&lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2018-scientific-tehcnical-books/MasteringRegularExpressions.jpg" class="u-pull-right" width="200px" style="max-width: 40%; margin-left: 20px"&gt;&lt;/p&gt;
&lt;h3&gt;Mastering Regular Expressions&lt;/h3&gt;
&lt;p&gt;Regular expressions are a whole world, and this is the book recommended by everyone to learn how to master them. I remember my friend Rafa who wrote infernal lines of &lt;em&gt;Chinese&lt;/em&gt;, as he called it, which were able to detect complicated patterns. Obviously they weren’t Chinese, but regular expressions; I hope this book helps me improve in this skill.&lt;/p&gt;
&lt;hr class="no-border u-cf"&gt;
&lt;p&gt;&lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2018-scientific-tehcnical-books/ProGit.png" class="u-pull-right" width="200px" style="max-width: 40%; margin-left: 20px"&gt;&lt;/p&gt;
&lt;h3&gt;Pro Git&lt;/h3&gt;
&lt;p&gt;For some years now, myself, and practically all programmers, use Git daily to manage the versions of our programs and projects. Git was revolutionary: a distributed version control system, with cryptographic guarantees, very fast... and free as in freedom. This book takes us beyond &lt;em&gt;pull, add, commit, push&lt;/em&gt;, and unveils the great potential behind this tool.&lt;/p&gt;
&lt;hr class="no-border u-cf"&gt;
&lt;p&gt;&lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2018-scientific-tehcnical-books/ProgrammingPearls.jpg" class="u-pull-right" width="200px" style="max-width: 40%; margin-left: 20px"&gt;&lt;/p&gt;
&lt;h3&gt;Programming Pearls&lt;/h3&gt;
&lt;p&gt;This book, a couple of chapters of which I had already read from a PDF a few years ago, contains authentic programming pearls. The author explains stories and some challenges, and we join him in the exploration of various solutions that show us the beauty that simple problems can hide.&lt;/p&gt;
&lt;hr class="no-border u-cf"&gt;
&lt;p&gt;&lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2018-scientific-tehcnical-books/Rust.jpeg" class="u-pull-right" width="200px" style="max-width: 40%; margin-left: 20px"&gt;&lt;/p&gt;
&lt;h3&gt;The Rust Programming Language&lt;/h3&gt;
&lt;p&gt;Rust is one of the most interesting programming languages released in recent years. It is revolutionary in the management of memory, making memory security a priority but without losing efficiency at runtime. This is the second edition of the official introduction to the language book. Although it is &lt;a href="https://doc.rust-lang.org/book/"&gt;available online&lt;/a&gt;,  for me it has always been easier to read a book such as this in paper.&lt;/p&gt;
&lt;h3&gt;The Contest Problem Book VII, VIII, IX&lt;/h3&gt;
&lt;p&gt;&lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2018-scientific-tehcnical-books/CPB9.jpg" class="u-pull-right" width="200px"&gt;
&lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2018-scientific-tehcnical-books/CPB8.jpg" class="u-pull-right" width="200px"&gt;
&lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2018-scientific-tehcnical-books/CPB7.jpg" class="u-pull-right" width="200px"&gt;&lt;/p&gt;
&lt;hr class="no-border u-cf"&gt;

&lt;p&gt;As the promoter of the &lt;a href="https://www.contrarellotge.cat/"&gt;&lt;em&gt;Contrarellotge matemàtica&lt;/em&gt; (in Catalan)&lt;/a&gt;, an online math contests site, I'm always looking for problems. These three books compile hundreds of math problems that have appeared in the American Mathematics Competitions.&lt;/p&gt;
&lt;hr class="no-border u-cf"&gt;
&lt;p&gt;&lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2018-scientific-tehcnical-books/DoingScience.jpg" class="u-pull-right" width="200px" style="max-width: 40%; margin-left: 20px"&gt;&lt;/p&gt;
&lt;h3&gt;Doing Science&lt;/h3&gt;
&lt;p&gt;A book with an atrocious cover which contains interesting recommendations and reflections regarding research and its communication. It discusses crucial matters such as data collection, statistical analysis, writing style, tables, figures... together with clear examples and providing historical context. A book that I recommend to anyone who is getting started in research.&lt;/p&gt;
&lt;hr class="no-border u-cf"&gt;
&lt;p&gt;&lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2018-scientific-tehcnical-books/TheElementsOfStyle.jpg" class="u-pull-right" width="200px" style="max-width: 40%; margin-left: 20px; margin-bottom:80px"&gt;&lt;/p&gt;
&lt;h3&gt;The Elements of Style&lt;/h3&gt;
&lt;p&gt;A classic guide for writing English. First published more than 100 years ago, it compiles lots of recommendations on writing that are still fully relevant. The book has been recommended by hundreds of journalists, writers, editors… it’s an ideal complement to &lt;em&gt;On Writing Well&lt;/em&gt;, which I read a few months ago, and will be great help for writing my thesis.&lt;/p&gt;</content><category term="2018-scientific-tehcnical-books"></category></entry><entry><title>30 interesting commands for the Linux shell</title><link href="https://www.thediligentdeveloper.com/30-interesting-shell-commands.html" rel="alternate"></link><published>2017-09-14T00:00:00+02:00</published><updated>2024-11-19T10:51:50+01:00</updated><author><name>Víctor López Ferrando</name></author><id>tag:www.thediligentdeveloper.com,2017-09-14:/30-interesting-shell-commands.html</id><summary type="html">&lt;blockquote&gt;
&lt;p&gt;This article got pretty big on &lt;strong&gt;Hacker News&lt;/strong&gt;, check the &lt;a href="https://news.ycombinator.com/item?id=15246302"&gt;discussion there&lt;/a&gt; for some interesting comments.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;These are 30 interesting commands and tips for the Linux shell that I have collected over the years.&lt;/p&gt;
&lt;h3&gt;1. Supervise command (run every 2s)&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;watch&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;ls -larth&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;2. Kill program using one port&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;sudo …&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</summary><content type="html">&lt;blockquote&gt;
&lt;p&gt;This article got pretty big on &lt;strong&gt;Hacker News&lt;/strong&gt;, check the &lt;a href="https://news.ycombinator.com/item?id=15246302"&gt;discussion there&lt;/a&gt; for some interesting comments.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;These are 30 interesting commands and tips for the Linux shell that I have collected over the years.&lt;/p&gt;
&lt;h3&gt;1. Supervise command (run every 2s)&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;watch&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;ls -larth&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;2. Kill program using one port&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;fuser&lt;span class="w"&gt; &lt;/span&gt;-k&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;8000&lt;/span&gt;/tcp
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;3. Limit memory usage for following commands&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nb"&gt;ulimit&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-Sv&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1000&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="c1"&gt;# 1000 KBs = 1 MB&lt;/span&gt;
&lt;span class="nb"&gt;ulimit&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-Sv&lt;span class="w"&gt; &lt;/span&gt;unlimited&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# Remove limit&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;4. Rename selected files using a regular expression&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;rename&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;s/\.bak$/.txt/&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;*.bak
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;5. Get full path of file&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;readlink&lt;span class="w"&gt; &lt;/span&gt;-f&lt;span class="w"&gt; &lt;/span&gt;file.txt
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;6. List contents of tar.gz and extract only one file&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;tar&lt;span class="w"&gt; &lt;/span&gt;tf&lt;span class="w"&gt; &lt;/span&gt;file.tgz
tar&lt;span class="w"&gt; &lt;/span&gt;xf&lt;span class="w"&gt; &lt;/span&gt;file.tgz&lt;span class="w"&gt; &lt;/span&gt;static
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;7. List files by size&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;ls&lt;span class="w"&gt; &lt;/span&gt;-lS
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;8. Nice trace route&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;mtr&lt;span class="w"&gt; &lt;/span&gt;google.com
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;9. Find files tips&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;find&lt;span class="w"&gt; &lt;/span&gt;.&lt;span class="w"&gt; &lt;/span&gt;-size&lt;span class="w"&gt; &lt;/span&gt;20c&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="c1"&gt;# By file size (20 bytes)&lt;/span&gt;
find&lt;span class="w"&gt; &lt;/span&gt;.&lt;span class="w"&gt; &lt;/span&gt;-name&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;*.gz&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-delete&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# Delete files&lt;/span&gt;
find&lt;span class="w"&gt; &lt;/span&gt;.&lt;span class="w"&gt; &lt;/span&gt;-exec&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;{}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\;&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="c1"&gt;# One file by line&lt;/span&gt;
./file1
./file2
./file3
find&lt;span class="w"&gt; &lt;/span&gt;.&lt;span class="w"&gt; &lt;/span&gt;-exec&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;{}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\+&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="c1"&gt;# All in the same line&lt;/span&gt;
./file1&lt;span class="w"&gt; &lt;/span&gt;./file2&lt;span class="w"&gt; &lt;/span&gt;./file3
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;10. Print text &lt;em&gt;ad infinitum&lt;/em&gt;&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;yes
yes&lt;span class="w"&gt; &lt;/span&gt;hello
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;11. Who is logged in?&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;w
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;12. Prepend line number&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;ls&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;nl
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;13. Grep with Perl like syntax (allows chars like \t)&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;grep&lt;span class="w"&gt; &lt;/span&gt;-P&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;\t&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;14. Cat backwards (starting from the end)&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;tac&lt;span class="w"&gt; &lt;/span&gt;file
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;15. Check permissions of each directory to a file&lt;/h3&gt;
&lt;p&gt;It is useful to detect permissions errors, for example when configuring
a web server.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;namei&lt;span class="w"&gt; &lt;/span&gt;-l&lt;span class="w"&gt; &lt;/span&gt;/path/to/file.txt
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;16. Run command every time a file is modified&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;while&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;inotifywait&lt;span class="w"&gt; &lt;/span&gt;-e&lt;span class="w"&gt; &lt;/span&gt;close_write&lt;span class="w"&gt; &lt;/span&gt;document.tex
&lt;span class="k"&gt;do&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;make
&lt;span class="k"&gt;done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;17. Copy to clipboard&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;cat&lt;span class="w"&gt; &lt;/span&gt;file.txt&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;xclip&lt;span class="w"&gt; &lt;/span&gt;-selection&lt;span class="w"&gt; &lt;/span&gt;clipboard
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;18. Spell and grammar check in Latex&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;detex&lt;span class="w"&gt; &lt;/span&gt;file.tex&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;diction&lt;span class="w"&gt; &lt;/span&gt;-bs
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You may need to install the following: &lt;code&gt;sudo apt-get install diction texlive-extra-utils&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;19. Check resources' usage of command&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;/usr/bin/time&lt;span class="w"&gt; &lt;/span&gt;-v&lt;span class="w"&gt; &lt;/span&gt;ls
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;20. Randomize lines in file&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;cat&lt;span class="w"&gt; &lt;/span&gt;file.txt&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;sort&lt;span class="w"&gt; &lt;/span&gt;-R
cat&lt;span class="w"&gt; &lt;/span&gt;file.txt&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;sort&lt;span class="w"&gt; &lt;/span&gt;-R&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;head&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# Pick a random sambple&lt;/span&gt;

&lt;span class="c1"&gt;# Even better (suggested by xearl in Hacker news):&lt;/span&gt;
shuf&lt;span class="w"&gt; &lt;/span&gt;file.txt
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;21. Keep program running after leaving SSH session&lt;/h3&gt;
&lt;p&gt;If the program doesn't need any interaction:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;nohup&lt;span class="w"&gt; &lt;/span&gt;./script.sh&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If you need to enter some input manually and then want to leave:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;./script.sh
&amp;lt;Type&lt;span class="w"&gt; &lt;/span&gt;any&lt;span class="w"&gt; &lt;/span&gt;input&lt;span class="w"&gt; &lt;/span&gt;you&lt;span class="w"&gt; &lt;/span&gt;want&amp;gt;
&amp;lt;Ctrl-Z&amp;gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="c1"&gt;# send process to sleep&lt;/span&gt;
&lt;span class="nb"&gt;jobs&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-l&lt;span class="w"&gt;           &lt;/span&gt;&lt;span class="c1"&gt;# find out the job id&lt;/span&gt;
&lt;span class="nb"&gt;disown&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-h&lt;span class="w"&gt; &lt;/span&gt;jobid&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="c1"&gt;# disown job&lt;/span&gt;
&lt;span class="nb"&gt;bg&lt;/span&gt;&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="c1"&gt;# continue running in the background&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Of course, you can also use &lt;code&gt;screen&lt;/code&gt; or &lt;code&gt;tmux&lt;/code&gt; for this purpose.&lt;/p&gt;
&lt;h3&gt;22. Run a command for a limited time&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;timeout&lt;span class="w"&gt; &lt;/span&gt;10s&lt;span class="w"&gt; &lt;/span&gt;./script.sh

&lt;span class="c1"&gt;# Restart every 30 minutes&lt;/span&gt;
&lt;span class="k"&gt;while&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;true&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;do&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;timeout&lt;span class="w"&gt; &lt;/span&gt;30m&lt;span class="w"&gt; &lt;/span&gt;./script.sh&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;23. Combine lines from two sorted files&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;comm&lt;span class="w"&gt; &lt;/span&gt;file1&lt;span class="w"&gt; &lt;/span&gt;file2
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Prints these three columns:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Lines unique to &lt;code&gt;file1&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Lines unique to &lt;code&gt;file2&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Lines both in &lt;code&gt;file1&lt;/code&gt; and &lt;code&gt;file2&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;With options &lt;code&gt;-1, -2, -3&lt;/code&gt;, you can remove each of these columns.&lt;/p&gt;
&lt;h3&gt;24. Split long file in files with same number of lines&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;split&lt;span class="w"&gt; &lt;/span&gt;-l&lt;span class="w"&gt; &lt;/span&gt;LINES&lt;span class="w"&gt; &lt;/span&gt;-d&lt;span class="w"&gt; &lt;/span&gt;file.txt&lt;span class="w"&gt; &lt;/span&gt;output_prefix
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;25. Flush swap partition&lt;/h3&gt;
&lt;p&gt;If a program eats too much memory, the swap can get filled with the rest of the
memory and when you go back to normal, everything is slow. Just restart the
swap partition to fix it:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;swapoff&lt;span class="w"&gt; &lt;/span&gt;-a
sudo&lt;span class="w"&gt; &lt;/span&gt;swapon&lt;span class="w"&gt; &lt;/span&gt;-a
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;26. Fix ext4 file system with problems with its superblock&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;fsck.ext4&lt;span class="w"&gt; &lt;/span&gt;-f&lt;span class="w"&gt; &lt;/span&gt;-y&lt;span class="w"&gt; &lt;/span&gt;/dev/sda1
sudo&lt;span class="w"&gt; &lt;/span&gt;fsck.ext4&lt;span class="w"&gt; &lt;/span&gt;-v&lt;span class="w"&gt; &lt;/span&gt;/dev/sda1
sudo&lt;span class="w"&gt; &lt;/span&gt;mke2fs&lt;span class="w"&gt; &lt;/span&gt;-n&lt;span class="w"&gt; &lt;/span&gt;/dev/sda1
sudo&lt;span class="w"&gt; &lt;/span&gt;e2fsck&lt;span class="w"&gt; &lt;/span&gt;-n&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;first&lt;span class="w"&gt; &lt;/span&gt;block&lt;span class="w"&gt; &lt;/span&gt;number&lt;span class="w"&gt; &lt;/span&gt;of&lt;span class="w"&gt; &lt;/span&gt;previous&lt;span class="w"&gt; &lt;/span&gt;list&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;/dev/sda1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;27. Create empty file of given size&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;fallocate&lt;span class="w"&gt; &lt;/span&gt;-l&lt;span class="w"&gt; &lt;/span&gt;1G&lt;span class="w"&gt; &lt;/span&gt;test.img
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;28. Manipulate PDFs from the command line&lt;/h3&gt;
&lt;p&gt;To join, shuffle, select, etc. &lt;code&gt;pdftk&lt;/code&gt; is a great tool:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;pdftk&lt;span class="w"&gt; &lt;/span&gt;*.pdf&lt;span class="w"&gt; &lt;/span&gt;cat&lt;span class="w"&gt; &lt;/span&gt;output&lt;span class="w"&gt; &lt;/span&gt;all.pdf&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="c1"&gt;# Join PDFs together&lt;/span&gt;
pdftk&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;A&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;.pdf&lt;span class="w"&gt; &lt;/span&gt;cat&lt;span class="w"&gt; &lt;/span&gt;A5&lt;span class="w"&gt; &lt;/span&gt;output&lt;span class="w"&gt; &lt;/span&gt;out.pdf&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# Extract page from PDF&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You can also manipulate the content with &lt;code&gt;cpdf&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;cpdf&lt;span class="w"&gt; &lt;/span&gt;-draft&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;.pdf&lt;span class="w"&gt; &lt;/span&gt;-o&lt;span class="w"&gt; &lt;/span&gt;out.pdf&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="c1"&gt;# Remove images&lt;/span&gt;
cpdf&lt;span class="w"&gt; &lt;/span&gt;-blacktext&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;.pdf&lt;span class="w"&gt; &lt;/span&gt;-o&lt;span class="w"&gt; &lt;/span&gt;out.pdf&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# Convert all text to black color&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;29. Monitor the progress in terms of generated output&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Write random data, encode it in base64 and monitor how fast it&lt;/span&gt;
&lt;span class="c1"&gt;# is being sent to /dev/null&lt;/span&gt;
cat&lt;span class="w"&gt; &lt;/span&gt;/dev/urandom&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;base64&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;pv&lt;span class="w"&gt; &lt;/span&gt;-lbri2&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;/dev/null

&lt;span class="c1"&gt;# pv options:&lt;/span&gt;
&lt;span class="c1"&gt;#   -l,  lines&lt;/span&gt;
&lt;span class="c1"&gt;#   -b,  total counter&lt;/span&gt;
&lt;span class="c1"&gt;#   -r,  show rate&lt;/span&gt;
&lt;span class="c1"&gt;#   -i2, refresh every 2 seconds&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;30. Find packages that have a given file in Ubuntu&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;apt-file&lt;span class="w"&gt; &lt;/span&gt;update
apt-file&lt;span class="w"&gt; &lt;/span&gt;search&lt;span class="w"&gt; &lt;/span&gt;dir/file.h
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</content><category term="2017-30-interesting-shell-commands"></category></entry><entry><title>My first scientific paper: PMut reinvented</title><link href="https://www.thediligentdeveloper.com/pmut-reinvented.html" rel="alternate"></link><published>2017-09-07T00:00:00+02:00</published><updated>2024-11-19T10:51:50+01:00</updated><author><name>Víctor López Ferrando</name></author><id>tag:www.thediligentdeveloper.com,2017-09-07:/pmut-reinvented.html</id><summary type="html">&lt;p&gt;Last July, my first scientific paper was published. Titled &lt;a href="https://academic.oup.com/nar/article/doi/10.1093/nar/gkx313/3769250/PMut-a-webbased-tool-for-the-annotation-of?guestAccessKey=09ff8f0f-6035-40b6-b0da-f2964d6f0865" target="_blank"&gt;PMut. A web-based tool for the annotation of pathological variants on proteins, 2017 update&lt;/a&gt;,
it is the result of more than two years work in my Ph.D. in bioinformatics. The paper
has been published in the English journal &lt;a href="https://academic.oup.com/nar" target="_blank"&gt;Nucleic Acids …&lt;/a&gt;&lt;/p&gt;</summary><content type="html">&lt;p&gt;Last July, my first scientific paper was published. Titled &lt;a href="https://academic.oup.com/nar/article/doi/10.1093/nar/gkx313/3769250/PMut-a-webbased-tool-for-the-annotation-of?guestAccessKey=09ff8f0f-6035-40b6-b0da-f2964d6f0865" target="_blank"&gt;PMut. A web-based tool for the annotation of pathological variants on proteins, 2017 update&lt;/a&gt;,
it is the result of more than two years work in my Ph.D. in bioinformatics. The paper
has been published in the English journal &lt;a href="https://academic.oup.com/nar" target="_blank"&gt;Nucleic Acids Research&lt;/a&gt;,
one of the main journals in the biomedicine field; specifically, it is part of the yearly web services special issue.&lt;/p&gt;
&lt;p&gt;In this blog article, I will try to summarize the most relevant points of the paper, ommiting the technical details. If you have not read the article &lt;a href="/introduction-to-my-research/"&gt;"Introduction to my research in bioinformatics"&lt;/a&gt;, I recommend it as an introduction to the context of my research.&lt;/p&gt;
&lt;h2&gt;Classic PMut&lt;/h2&gt;
&lt;p&gt;PMut is a predictor of the pathology of protein mutations. That is, it is a computer program that, given a mutation in a protein, gives us a prediction of whether this mutation will cause a disease or it will be harmless.&lt;/p&gt;
&lt;p&gt;This idea is not new, in fact the PMut predictor was created in 2005 and has been one of the most widely used predictors since then. However, during this last decade, the predictive methods have evolved dramatically and the number of mutations analyzed in the lab has increased by a factor of 10. Thus, I took the challenge of updating this predictor, and this scientific paper is the first result of my work.&lt;/p&gt;
&lt;h2&gt;The PyMut prediction engine&lt;/h2&gt;
&lt;p&gt;As a prelude to the development of a new predictor, we have developed the PyMut prediction engine in the form of a Python package. This software, &lt;a href="https://github.com/vlopezferrando/pymut/"&gt;publicly available&lt;/a&gt;, is capable of managing all the tasks related to pathology predictions: the calculation of numerical descriptors of mutations, the training of predictors, the evaluation of these, the generation of related charts, etc. Here are some examples of the charts we can get using PyMut:&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2017-my-first-paper/pymut.png" width="500px"&gt;
&lt;em&gt;Examples of charts generated using PyMut.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;With the PyMut package, everyone can replicate on their computer the process of preparing, testing and using a predictor such as PMut.&lt;/p&gt;
&lt;h2&gt;The new PMut2017 predictor&lt;/h2&gt;
&lt;p&gt;Using the PyMut engine, and training with the SwissVar database, which contains 27,203 pathogenic mutations and 38,078 neutral mutations over more than 12,000 different proteins, we have trained the PMut2017 predictor.&lt;/p&gt;
&lt;p&gt;Before giving the predictor for good, it is crucial to evaluate its reliability. In fact, the journal demands a very strict study of its precision, and for this reason we have followed 4 different approaches:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;10-fold cross-validation. It consists of dividing the training data into 10 sets, training a predictor with 9 of them and evaluating with the one that has been excluded. We repeat this procedure 10 times, excluding a different set every time and averaging the results. This is the easiest way to obtain an approximation of the reliability of the predictor.&lt;/li&gt;
&lt;li&gt;Blind test using new SwissVar data. We move to December 2015, and train a predictor with the data that was available back then in SwissVar. Then, we evaluate the 3,166 mutations that were added to SwissVar during 2016.&lt;/li&gt;
&lt;li&gt;ClinVar data. Clinvar is another database of annotated mutations, significantly different from SwissVar. We have evaluated how good are the predictions of PMut2017 on the Clinvar mutations that are not present in SwissVar.&lt;/li&gt;
&lt;li&gt;Study of specific genes. We compared how PMut2017 works for some specific genes, comparing the results with some of the most widely used predictors.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2017-my-first-paper/comp.png" width="500px"&gt;
&lt;em&gt;Comparison of PMut with other predictors. The most relevant metric is the Matthews Correlations Coefficient (MCC, last column), for which a higher number means better predictions. See the &lt;a href="https://academic.oup.com/nar/article/doi/10.1093/nar/gkx313/3769250/PMut-a-webbased-tool-for-the-annotation-of?guestAccessKey=09ff8f0f-6035-40b6-b0da-f2964d6f0865"&gt;article&lt;/a&gt; to understand the details of the table.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;All these assessments have allowed us to compare PMut2017 with the most accurate predictors and to verify that it is undoubtedly among the most powerful ones.&lt;/p&gt;
&lt;h2&gt;The PMut web portal&lt;/h2&gt;
&lt;p&gt;To make predictions accessible to the research community, we facilitate the use of PMut2017 from a &lt;a href="http://mmb.pcb.ub.es/PMut/"&gt;web page&lt;/a&gt; open to everyone. Users can send a list of mutations through a form and obtain the corresponding predictions.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2017-my-first-paper/web.png" width="500px"&gt;
&lt;em&gt;Screenshots of the web portal.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;The vast majority of users ask for the impact of mutations on human proteins. In order to streamline these calculations, and since I do the Ph.D. in the Barcelona Supercomputing Center and we like to use the enormous supercomputer we have, we decided to pre-calculate some predictions. In fact not only some, but &lt;em&gt;all&lt;/em&gt; the possible mutations in &lt;em&gt;all&lt;/em&gt; human proteins, that is, a total of 725,596,928 mutations over 106,407 proteins. These predictions, stored in a MongoDB database, are immediately accessible without the need for any calculation.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2017-my-first-paper/mn4.jpg" width="500px"&gt; &lt;em&gt;Marenostrum 4, BSC's supercomputer, has a computing power of 11.1 Petaflops, that is to say, 11.1 &amp;times; 10&lt;sup&gt;15&lt;/sup&gt; operations per second. Marenostrum 4 was released in July 2017; for my computations I used the late Marenostrum 3.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;The PMut portal also offers the novel possibility of training specific predictors.
This functionality is especially relevant to those researchers that work
on one or more specific proteins. These researchers, who usually
have more data than the public, can easily train a custom predictor
and use it for their specific research.&lt;/p&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;In summary, in this work we have published a new predictor as accurate as the best predictors currently available. In addition, we share the code we used to train it, released as a Python package. Finally, we make all these functions accessible from a web portal where, for the first time, researchers can train &amp;mdash;in a fully automatic way&amp;mdash; tailor-made predictors for their studies.&lt;/p&gt;</content><category term="2017-my-first-paper"></category></entry><entry><title>Introduction to my research in bioinformatics</title><link href="https://www.thediligentdeveloper.com/introduction-to-my-research.html" rel="alternate"></link><published>2017-05-08T12:00:00+02:00</published><updated>2024-11-19T10:51:50+01:00</updated><author><name>Víctor López Ferrando</name></author><id>tag:www.thediligentdeveloper.com,2017-05-08:/introduction-to-my-research.html</id><summary type="html">&lt;p&gt;Two and a half years ago I started my PhD in bioinformatics, a wide field of research closely related to biomedicine, which was totally unknown to me at that time. Biomedicine seeks the understanding (and treatment) of diseases at a molecular and biological scale, and bioinformatics adds the use of …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Two and a half years ago I started my PhD in bioinformatics, a wide field of research closely related to biomedicine, which was totally unknown to me at that time. Biomedicine seeks the understanding (and treatment) of diseases at a molecular and biological scale, and bioinformatics adds the use of computational tools in this research. In this article I will make an introduction to my research, contextualizing it in the more general biomedical research field.&lt;/p&gt;
&lt;h4&gt;DNA, genes and proteins&lt;/h4&gt;
&lt;p&gt;All cells in our body (and any organism in general), contain huge molecules in the form of lengthy threads, which we call &lt;strong&gt;DNA&lt;/strong&gt;. DNA is very important, because it acts like a big book of instructions for the development of living organisms.&lt;/p&gt;
&lt;p&gt;&lt;img alt="DNA contained in the nucleus of a cell" src="https://www.thediligentdeveloper.com/lopezferrando/2017-introduction-to-my-research/dna.png"&gt;&lt;em&gt;Source: bbc.com/education&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;In the long thread which DNA is, there are pieces that are particularly important and are what we call &lt;strong&gt;genes&lt;/strong&gt;. Genes are special because they contain some very specific information: the instructions to make &lt;strong&gt;proteins&lt;/strong&gt;. Proteins, which can be imagined as tiny machines, are crucial to life because they perform all kinds of tasks: transporting components, accelerating chemical reactions, communicating signals, etc.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Myoglobin" src="https://www.thediligentdeveloper.com/lopezferrando/2017-introduction-to-my-research/myoglobin.jpg"&gt;&lt;em&gt;Example protein: myoglobin, which is responsible for transporting oxygen in muscle tissue.&lt;br&gt;Source: wikipedia.org&lt;/em&gt;&lt;/p&gt;
&lt;h4&gt;Mutations&lt;/h4&gt;
&lt;p&gt;As we all know thanks to many TV series, the DNA of each person is different. But how different is it? In fact, the DNA of individuals is the same in 99.9% of the sequence, especially in the genes: we all need the same proteins to perform the same functions and therefore our genes are almost identical. When there are differences, they are usually in the form of single point mutations: specific changes in the DNA sequence. These mutations, when they occur on a gene, may also mean that the protein also has a mutation.&lt;/p&gt;
&lt;p&gt;When we talk about mutations, we are not talking about abstract or unknown entities, as we have techniques nowadays that can find the mutations in the DNA of people. Some tools that in recent years have been taking more and more significance are the DNA sequencing machines, which are able to “read” a person's DNA. For example, they can be used to detect differences between cancer cells and healthy cells from the same patient to try to understand how the disease is developing in a particular case.&lt;/p&gt;
&lt;p&gt;&lt;img alt="DNA sequencer" src="https://www.thediligentdeveloper.com/lopezferrando/2017-introduction-to-my-research/seq.jpg"&gt;&lt;em&gt;DNA Sequencer: great strides over the past decade have meant that “reading” DNA is now be very affordable.&lt;br&gt;Source: illumina.com&lt;/em&gt;&lt;/p&gt;
&lt;h4&gt;Mutations and diseases&lt;/h4&gt;
&lt;p&gt;Hence, are mutations in proteins &lt;em&gt;good&lt;/em&gt; or &lt;em&gt;bad&lt;/em&gt;? The answer is that it depends. Most mutations are harmless, we could even say that they are good because they don’t cause any harm, they allow the variety of living organisms and are key to evolution. However, some mutations are also the root cause of many diseases, for example by modifying the shape of a protein and preventing the fulfillment of its functions.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Red blood cells" src="https://www.thediligentdeveloper.com/lopezferrando/2017-introduction-to-my-research/sickle.jpg"&gt;&lt;em&gt;Healthy red blood cells and aberrant red blood cells (“banana”-shaped) due to a mutation in hemoglobin.&lt;br&gt;Source: britannica.com&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Finding out whether a mutation is bad or not is difficult and expensive. It is part of the work that many researchers do around the world, trying to discover the molecular-scale implications of mutations in the development of various diseases. These findings are usually made public and put together, and so there are databases of mutations classified as benign or pathological. These databases, which in some cases contain more than 100,000 mutations, are still too small and contain only a small fraction of all the mutations that can be found in patients. Therefore, we need more tools to differentiate between benign and pathological mutations...&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Can computers help in any way?&lt;/strong&gt;&lt;/p&gt;
&lt;h4&gt;Pathology computer predictors&lt;/h4&gt;
&lt;p&gt;Computer science, and machine learning more specifically, provide us with tools that can help us classify mutations as either pathological or benign. Even though these methods will not be as reliable as the evidence obtained in the lab, they can be a great help for other researchers, pointing at promising leads and helping in the interpretation of large amounts of data. The first pathology predictors were developed 15 years ago, they are computer programs based on various methods that are able to predict (with an accuracy that does'nt usually exceed the 90%, but that can get close in some cases) the pathology of mutations.&lt;/p&gt;
&lt;p&gt;In 2004, a team of researchers from Barcelona (including the advisors of my thesis), developed &lt;strong&gt;PMut&lt;/strong&gt;, one of the first predictors that has been widely used since. When I started my PhD, I was commissioned to put the predictor up-to-date. Much has happened since 2004, the mutations databases are 10 times larger, and great advances in predictive methods have been made. The “simple” task of updating the PMut predictor has lead to research on how to improve predictors, deepen in the understanding of mutations and the strengths and weaknesses of these predictors.&lt;/p&gt;
&lt;p&gt;Soon I will publish a blog article explaining my first contributions to this field and the specific lines of my research.&lt;/p&gt;</content><category term="2017-introduction-to-my-research"></category></entry><entry><title>A brief history of the Web... and web development</title><link href="https://www.thediligentdeveloper.com/a-brief-history-of-the-web-and-web-development.html" rel="alternate"></link><published>2016-10-13T12:00:00+02:00</published><updated>2024-11-19T10:51:50+01:00</updated><author><name>Víctor López Ferrando</name></author><id>tag:www.thediligentdeveloper.com,2016-10-13:/a-brief-history-of-the-web-and-web-development.html</id><summary type="html">&lt;p&gt;&lt;link rel="stylesheet" type="text/css" href="https://www.thediligentdeveloper.com/lopezferrando/2016-web-development-history/slick/slick.css"/&gt;
&lt;link rel="stylesheet" type="text/css" href="https://www.thediligentdeveloper.com/lopezferrando/2016-web-development-history/style.css"/&gt;&lt;/p&gt;
&lt;div style="display: none"&gt;
  {static}en1.png
&lt;/div&gt;

&lt;div class="slick"&gt;
  &lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2016-web-development-history/en1.png"&gt;
  &lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2016-web-development-history/en2.png"&gt;
  &lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2016-web-development-history/en3.png"&gt;
  &lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2016-web-development-history/en4.png"&gt;
  &lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2016-web-development-history/en5.png"&gt;
  &lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2016-web-development-history/en6.png"&gt;
  &lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2016-web-development-history/en7.png"&gt;
  &lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2016-web-development-history/en8.png"&gt;
  &lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2016-web-development-history/en9.png"&gt;
  &lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2016-web-development-history/en10.png"&gt;
  &lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2016-web-development-history/en11.png"&gt;
  &lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2016-web-development-history/en12.png"&gt;
  &lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2016-web-development-history/en13.png"&gt;
  &lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2016-web-development-history/en14.png"&gt;
  &lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2016-web-development-history/en15.png"&gt;
  &lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2016-web-development-history/en16.png"&gt;
  &lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2016-web-development-history/en17.png"&gt;
  &lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2016-web-development-history/en18.png"&gt;
  &lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2016-web-development-history/en19.png"&gt;
  &lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2016-web-development-history/en20.png"&gt;
  &lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2016-web-development-history/en21.png"&gt;
  &lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2016-web-development-history/en22.png"&gt;
  &lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2016-web-development-history/en23.png"&gt;
  &lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2016-web-development-history/en24.png"&gt;
  &lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2016-web-development-history/en25.png"&gt;
  &lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2016-web-development-history/en26.png"&gt;
  &lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2016-web-development-history/en27.png"&gt;
  &lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2016-web-development-history/en28.png"&gt;
  &lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2016-web-development-history/en29.png"&gt;
  &lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2016-web-development-history/en30.png"&gt;
  &lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2016-web-development-history/en31.png"&gt;
  &lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2016-web-development-history/en32.png"&gt;
  &lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2016-web-development-history/en33.png"&gt;
  &lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2016-web-development-history/en34.png"&gt;
  &lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2016-web-development-history/en35.png"&gt;
  &lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2016-web-development-history/en36.png"&gt;
  &lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2016-web-development-history/en37.png"&gt;
  &lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2016-web-development-history/en38.png"&gt;
  &lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2016-web-development-history/en39.png"&gt;
  &lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2016-web-development-history/en40.png"&gt;
  &lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2016-web-development-history/en41.png"&gt;
  &lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2016-web-development-history/en42.png"&gt;
&lt;/div&gt;

&lt;div style="text-align: center"&gt;
  &lt;span id="slide-number"&gt;1&lt;/span&gt; of &lt;span id="slide-count"&gt;42&lt;/span&gt;&lt;/div&gt;

&lt;div id="slide-notes"&gt;
  &lt;p&gt;This is a presentation I prepared to introduce a course
    on web programming. It reviews the evolution of the Web
    since its creation and how web development has changed over the years.
    The first website was published only 25 years ago, and it is …&lt;/p&gt;&lt;/div&gt;</summary><content type="html">&lt;p&gt;&lt;link rel="stylesheet" type="text/css" href="https://www.thediligentdeveloper.com/lopezferrando/2016-web-development-history/slick/slick.css"/&gt;
&lt;link rel="stylesheet" type="text/css" href="https://www.thediligentdeveloper.com/lopezferrando/2016-web-development-history/style.css"/&gt;&lt;/p&gt;
&lt;div style="display: none"&gt;
  {static}en1.png
&lt;/div&gt;

&lt;div class="slick"&gt;
  &lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2016-web-development-history/en1.png"&gt;
  &lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2016-web-development-history/en2.png"&gt;
  &lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2016-web-development-history/en3.png"&gt;
  &lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2016-web-development-history/en4.png"&gt;
  &lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2016-web-development-history/en5.png"&gt;
  &lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2016-web-development-history/en6.png"&gt;
  &lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2016-web-development-history/en7.png"&gt;
  &lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2016-web-development-history/en8.png"&gt;
  &lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2016-web-development-history/en9.png"&gt;
  &lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2016-web-development-history/en10.png"&gt;
  &lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2016-web-development-history/en11.png"&gt;
  &lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2016-web-development-history/en12.png"&gt;
  &lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2016-web-development-history/en13.png"&gt;
  &lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2016-web-development-history/en14.png"&gt;
  &lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2016-web-development-history/en15.png"&gt;
  &lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2016-web-development-history/en16.png"&gt;
  &lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2016-web-development-history/en17.png"&gt;
  &lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2016-web-development-history/en18.png"&gt;
  &lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2016-web-development-history/en19.png"&gt;
  &lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2016-web-development-history/en20.png"&gt;
  &lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2016-web-development-history/en21.png"&gt;
  &lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2016-web-development-history/en22.png"&gt;
  &lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2016-web-development-history/en23.png"&gt;
  &lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2016-web-development-history/en24.png"&gt;
  &lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2016-web-development-history/en25.png"&gt;
  &lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2016-web-development-history/en26.png"&gt;
  &lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2016-web-development-history/en27.png"&gt;
  &lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2016-web-development-history/en28.png"&gt;
  &lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2016-web-development-history/en29.png"&gt;
  &lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2016-web-development-history/en30.png"&gt;
  &lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2016-web-development-history/en31.png"&gt;
  &lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2016-web-development-history/en32.png"&gt;
  &lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2016-web-development-history/en33.png"&gt;
  &lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2016-web-development-history/en34.png"&gt;
  &lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2016-web-development-history/en35.png"&gt;
  &lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2016-web-development-history/en36.png"&gt;
  &lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2016-web-development-history/en37.png"&gt;
  &lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2016-web-development-history/en38.png"&gt;
  &lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2016-web-development-history/en39.png"&gt;
  &lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2016-web-development-history/en40.png"&gt;
  &lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2016-web-development-history/en41.png"&gt;
  &lt;img src="https://www.thediligentdeveloper.com/lopezferrando/2016-web-development-history/en42.png"&gt;
&lt;/div&gt;

&lt;div style="text-align: center"&gt;
  &lt;span id="slide-number"&gt;1&lt;/span&gt; of &lt;span id="slide-count"&gt;42&lt;/span&gt;&lt;/div&gt;

&lt;div id="slide-notes"&gt;
  &lt;p&gt;This is a presentation I prepared to introduce a course
    on web programming. It reviews the evolution of the Web
    since its creation and how web development has changed over the years.
    The first website was published only 25 years ago, and it is nice
    to know the technology that allowed such a great expansion in order
    to understand web programming nowadays.
    &lt;p&gt; The story is very simplified and is made from my
    subjective point of view, giving more importance to technologies
    that I have personally used. Hope you like it!
&lt;/div&gt;

&lt;script&gt;
  var NOTES = [`
  &lt;p&gt;This is a presentation I prepared to introduce a course
    on web programming. It reviews the evolution of the Web
    since its creation and how web development has changed over the years.
    The first website was published only 25 years ago, and it is nice
    to know the technology that allowed such a great expansion in order
    to understand web programming nowadays.
    &lt;p&gt; The story is very simplified and is made from my
    subjective point of view, giving more importance to technologies
    that I have personally used. Hope you like it!
  `, `
    &lt;p&gt;Before the Web could exist, the Internet had to be invented.
    This means the creation of communication networks and protocols
    to transmit the data, notably IP (Internet
    Protocol) and TCP (Transmission Control Protocol).
    &lt;p&gt; When these challenges were overcome, it was the time to start thinking
    about the Web...
  `, `
    The main protocol for the Web is HTTP
    (Hyper Text Transfer Protocol),
    which defines how a server should answer client requests.
    Users can request data
    (GET, like when you access some website),
    send data (POST, as in submitting a form),
    DELETE (to remove some resource), etc.
    All these operations are defined in the HTTP protocol.
  `, `
    In addition to HTTP, HTML (Hyper Text Markup Language) was born.
    It is a language that specifies how to shape the content;
    for example, the main and secondary titles
    are surrounded by the tags &lt;code&gt;&amp;lt;h1&amp;gt;&amp;lt;/h1&amp;gt;&lt;/code&gt; and
    &lt;code&gt;&amp;lt;h2&amp;gt;&amp;lt;/h2&amp;gt;&lt;/code&gt;, text is shown in bold using
    &lt;code&gt;&amp;lt;b&amp;gt;&amp;lt;/b&amp;gt;&lt;/code&gt;, etc.
    The most important tag is
    &lt;code&gt;&amp;lt;a href=""&amp;gt;&amp;lt;/a&amp;gt;&lt;/code&gt;, which introduces
    &lt;strong&gt;hyperlinks&lt;/strong&gt; to other websites.
  `, `
    Another protocol that was defined is URI:
    Uniform Resource Identifier, which
    details how resources should be named in order to be found.
    Some of the decisions made have long been regretted,
    and we still maintain the tedious &lt;code&gt;http://&lt;/code&gt;
    at the beginning of each URL.
  `, `
    Finally, users need a tool to integrate all these
    protocols: manage URLs, communicate with
    servers, display HTML, etc.: the &lt;strong&gt;Web Browser&lt;/strong&gt;.
  `, `
    Having developed all this, in 1991 the first website was published in
    CERN,
    and this technology spread initially to other scientific communities.
  `, `
    Since 1992, the Web attracted more and more people.
    Windows 95 was the operating system on which many people surfed the web
    for the first time, and they did it using
    Netscape or Internet Explorer.
  `, `
    At that time, websites were text files written in HTML and
    kept in a server (computer with internet connection delivering these to
    whoever requested them). The HTML contained text, links and
    style: font, size, color, underlining, etc. We say that the Web was
    &lt;strong&gt;static&lt;/strong&gt; because its content did not change,
    everyone received the same
    HTML file until somebody modified it in the server.
  `, `
    Vilaweb is an example of a pioneer website: the first digital newspaper in Catalan.
  `, `
    Here is the website of the University of Barcelona at Christmas 1996.
  `, `
    And the website of the Government of Catalonia (Generalitat de Catalunya) in 1997.
  `, `
    Despite the high growth (1 million websites in 1996), this technology had
    limitations: the content was static and therefore it was difficult to show
    different pages to different users (like when you login to a service).
    Also, the style of the sites was poor and people had to do tricks to enhance it.
  `, `
    Between 2000 and 2006 there was the explosion of the dynamic web, in which
    content changed often. A great example is Wikipedia, which
    appeared in this period, and allowed anyone to edit the pages.
    Mozilla Firefox appeared to compete with
    Internet Explorer, and Linux became popular among "human beings"
    thanks to Ubuntu.
  `, `
    The web styling was separated from the content thanks to CSS
    (Cascading Style Sheets): with it you can set colors, sizes,
    spacing, backgrounds, etc. In addition to adding
    many styling options, it enabled a centralized style definition,
    so that a change in the CSS file would update the style of all the different pages
    in a site.
  `, `
    &lt;p&gt;As for the server, dynamic sites were mostly based on
    the &lt;strong&gt;LAMP&lt;/strong&gt; architecture:&lt;/p&gt;
    &lt;ul&gt;
      &lt;li&gt;&lt;strong&gt;Linux&lt;/strong&gt; is the operating system par excellence,
        it is free and gives users the freedom to configure it as they like.
      &lt;li&gt; &lt;strong&gt;Apache&lt;/strong&gt; as the web server. It is free software and
        offers great efficiency and stability. It will take many years for
        it to have serious competitors.
      &lt;li&gt;&lt;strong&gt;MySQL&lt;/strong&gt; is the database that stores the
        dynamic content of the websites: user data,
        blog articles, comments, etc.
      &lt;li&gt; &lt;strong&gt;PHP&lt;/strong&gt; is the programming language in which
        the vast majority of websites were programmed.
    &lt;/ul&gt;
  `, `
    When a user (client) requests a dynamic page, the web server (Apache), calls
    a PHP program. PHP communicates with MySQL to get the data and generates an HTML output
    that hands to Apache, who serves it to the client. And all these programs
    run on a Linux server.
  `, `
    One example of LAMP application is Wikipedia, which appeared in 2003.
  `, `
    Wordpress (2005) is also programmed using a LAMP architecture.
  `, `
    &lt;p&gt;Pages with dynamic content are usually pretty fun, but can we do
    them more attractive? Have showy things happen?
    &lt;p&gt;
    One option would be to use
    JavaScript. JavaScript is a programming language that browsers
    understand and execute, which can modify the contents of a web page
    once it has been loaded. For example, it can be used to display a countdown or
    show and hide menus and submenus.
    The problem with JavaScript is that it is very slow, has an unpopular syntax
    and this means that very few people take it seriously.
  `, `
    Another option is to use Flash, which allows us to show animations and play music
    and video. In these years many pages appeared featuring games made with Flash,
    and YouTube, for example, was based on Flash for many years.
  `, `
    Another option is to use Java applets. A Java applet is a complete program
    that the user downloads and runs on their computer. Java is much
    faster than JavaScript, and being a program running outside the browser,
    it is able to do many more things. Some programs by the administration, for example,
    were (or are) Java applets.
  `, `
    Regarding web interaction, we have not really found a final solution.
    JavaScript is an ugly and slow language, and Flash and Java need the users
    to install other programs, and so don't reach everyone. Web developers
    also have their problems, they want to program websites faster:
    we want to make a website every week!
  `, `
    Between 2007 and 2011 the interactivity of websites consolidated. We saw the birth of
    social networks, and even a new competitor emerged in the browsers market: Chrome.
  `, `
    One of the buzzwords these years was AJAX Asynchronous
    JavaScript and XML. Wat?
  `, `
    AJAX is basically the fact of updating a site's content without needing
    to refresh the page. Indeed, this was a very important innovation!
  `, `
    One of the first services which introduced it was GMail. When you send an email,
    you return to the inbox without a page refresh, and while you type
    the recipient, Gmail will recommend you addresses of your contacts.
  `, `
    Regarding the server-side development, some problems were also identified.
    It often happens that the PHP code looks like a bowl of spaghetti, and this is not
    good. When code is chaotic, it is difficult to make changes and
    identify errors.
  `, `
    Some people realized that web applications very often did the
    same: create, read, update or delete data (articles from a blog,
    forum messages, comments...), manage users, display
    the content in different languages,
    process user-sent data from forms, etc. A code organization pattern
    became remarkably popular: Model-View-Controller.
  `, `
    The Model defines the types of data that we handle (users, articles, comments),
    the View is responsible for generating the HTML, and the Controller communicates with
    everyone, manages URLs, processess the data that users send, etc.
  `, `
    Some frameworks were created following the Model-View-Controller
    pattern and providing a lot of tools
    commonly used in web applications. These frameworks allow the developer to
    focus on its current project, and not on boring and repetitive tasks.
    There are frameworks for all tastes and programming languages, but
    Ruby on Rails is probably the most popular one
    (even though I like Django better! :P).
  `, `
    These frameworks fit in the LAMP as a substitute to the &amp;mdash; often
    chaotic&amp;mdash; PHP code.
  `, `
    Many famous services such as Twitter,
    Instagram, Pinterest and Groupon were developed using Ruby on Rails
    or Django.
  `, `
    We should also mention that together with the big frameworks mentioned,
    some microframeworks also appeared, aiming to simplify
    the implementation of simple websites.
  `, `
    We reach 2012, when smartphones spread everywhere
    and people demand lovely websites, fast, and
    with elements sliding gently.
  `, `
    The standards HTML5 and CSS3 consolidate. Using them we can include videos
    audio, drawing canvas, vector images (in we can zoom as much as we want),
    mathematical formulas and much more! To implement all this is the
    browsers' job, and great advances in recent years have meant that almost
    everyone has access to all these components.
  `, `
    JavaScript, the language that everyone despised, that was slow and was only meant to provide
    countdowns, is reborn! V8, a Google developed virtual machine (a
    tool to run JavaScript) is added to Chrome, and it is sooo fast!
    This allows the creation of such impressive applications as Google Docs, a fully-featured
    text processor implemented in JavaScript and running in the browser.
  `, `
    Like vultures, programmers will soon get to do frameworks for the
    JavaScript included in the websites, and we could name AngularJS
    (Google) and React (Facebook) as two of most popular nowadays.
  `, `
    Important news is that the JavaScript programming language also lands on the server.
    Being faster than Python, Ruby or PHP (thanks to V8),
    and as programmers already use it in the client, why not use the same
    language in the server? NodeJS is trendiest way to use JavaScript on the server.
  `, `
    As for the future, what trends can we identify?
  `, `
    &lt;p&gt;We have recently started to hear about the Web 3.0, and it is funny how
    some of the creators of Web 1.0 are the ones talking about it. During the last deacade, the
    Internet has increasingly become a tool of control, governments and large
    corporations accumulate power and benefit from their dominant position.
    &lt;p&gt;To return to an open web, free and safe as it was dreamed
    two decades ago, there is interest in decentralizing the web architecture,
    making it more difficult for monopolies to maintain the current tendency.
  `, `
    Developing rich websites with high interactivity and elaborate components
    will be made easier every time. Also, we will tend to unify the implementation
    of services on different devices: websites, Android apps, iOS apps, etc.
    projects such as React Native are leading the way.
  `];
&lt;/script&gt;

&lt;p&gt;&lt;script
              src="https://code.jquery.com/jquery-3.7.0.min.js"
              integrity="sha256-2Pmvv0kuTBOenSvLm6bvfBSSHrUJ+3A7x6P5Ebd07/g="
              crossorigin="anonymous"&gt;&lt;/script&gt;
&lt;/p&gt;
&lt;script src="https://www.thediligentdeveloper.com/lopezferrando/2016-web-development-history/slick/slick.min.js"&gt;&lt;/script&gt;
&lt;script&gt;
    $(document).ready(function() {
      $('.slick').slick({
        'prevArrow': '&lt;span class="button button-sm button-slide slick-prev"&gt;⇽&lt;/span&gt;',
        'nextArrow': '&lt;span class="button button-sm button-slide slick-next"&gt;⇾&lt;/span&gt;',
        infinite: false,
        lazyLoad: 'progressive',
        slidesToShow: 1,
        slidesToScroll: 1,
        waitForAnimate: false
      });
      $('.slick').on('beforeChange', function(e, slick, currentSlide, nextSlide) {
        /* Posar el número d'slide */
        $('#slide-number').text(nextSlide + 1);
        $('#slide-count').text(currentSlide.slideCount);

        /* Posar les notes */
        $('#slide-notes').html(NOTES[nextSlide]);
      });
    });
  &lt;/script&gt;</content><category term="2016-web-development-history"></category></entry><entry><title>The two aces paradox</title><link href="https://www.thediligentdeveloper.com/two-aces-paradox.html" rel="alternate"></link><published>2016-07-25T12:00:00+02:00</published><updated>2024-11-19T10:51:50+01:00</updated><author><name>Víctor López Ferrando</name></author><id>tag:www.thediligentdeveloper.com,2016-07-25:/two-aces-paradox.html</id><summary type="html">&lt;p&gt;A few days ago my former programming teammate Ivan Geffner presented me a
curious mathematical paradox that I will now explain. This problem appears in
the book &lt;em&gt;Reasoning about uncertainty&lt;/em&gt; by Joseph Halpern, a professor at
Cornell University, where Ivan is doing his doctorate. Let's see what it is.&lt;/p&gt;
&lt;h3&gt;The …&lt;/h3&gt;</summary><content type="html">&lt;p&gt;A few days ago my former programming teammate Ivan Geffner presented me a
curious mathematical paradox that I will now explain. This problem appears in
the book &lt;em&gt;Reasoning about uncertainty&lt;/em&gt; by Joseph Halpern, a professor at
Cornell University, where Ivan is doing his doctorate. Let's see what it is.&lt;/p&gt;
&lt;h3&gt;The game&lt;/h3&gt;
&lt;p&gt;A friend of ours presents us a game using four cards (from the Spanish deck): the
ace of &lt;em&gt;golds&lt;/em&gt;, ace of &lt;em&gt;spades&lt;/em&gt;, the three and four of &lt;em&gt;cups&lt;/em&gt;. Repeatedly, our
friend shuffles these four cards and we pick two of them at random:&lt;/p&gt;
&lt;p&gt;&lt;img alt="Random cards" src="https://www.thediligentdeveloper.com/tria.png"&gt; &lt;em&gt;We randomly choose two cards from these four.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Then he offers a deal:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&amp;mdash;Would you bet 1€ to having both aces? If you do have them, I will give you 4€.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;As we are reasonable people, we will make some small probability calculations
before entering the game. We note that there are six possible combinations of
two cards, all equally probable:&lt;/p&gt;
&lt;p&gt;&lt;img alt="Possibles combinations of cards" src="https://www.thediligentdeveloper.com/parelles.png"&gt; &lt;em&gt;The six possible
choices of two cards&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;So, ultimately, we will win only 1 time in 6, and thus lose 6€ in order to win only 4€.
So we tell our friend: &lt;strong&gt;I will not play&lt;/strong&gt;!&lt;/p&gt;
&lt;p&gt;Our friend keeps shuffling the four cards and handing us two of them. He looks
at the cards we have discarded, and to make the game more attractive to us, he
says:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Proposal #1&lt;/strong&gt;. &amp;mdash;&lt;strong&gt;I can see you at least have an ace, do you want to play now?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="" class="mostra-solucio-parent-next"&gt;Show answer&lt;/a&gt;&lt;/p&gt;
&lt;div class="solucio"&gt;
&lt;p&gt;Of the six initial combinations, we can dismiss the case where we have the three
  and the four, because we know that at least we have one ace. Then there are five
  possibilities:&lt;/p&gt;
&lt;p&gt;&lt;img alt="Combinations with an ace" src="https://www.thediligentdeveloper.com/un_as.png"&gt;&lt;/p&gt;
&lt;p&gt;In 1 case out of 5 we have two aces, so we have to spend 5€ to earn 4€.
  The answer is the same as before: &lt;strong&gt;I do not play&lt;/strong&gt;!&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Making a great effort, our friend keeps dealing and trying to offer us even
better deals, like this one:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Proposal #2&lt;/strong&gt;. &amp;mdash;&lt;strong&gt;Now you have the ace of &lt;em&gt;golds&lt;/em&gt;, do you want to play?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="" class="mostra-solucio-parent-next"&gt;Show answer&lt;/a&gt;&lt;/p&gt;
&lt;div class="solucio"&gt;
&lt;p&gt;Because we know that we have the ace of &lt;em&gt;golds&lt;/em&gt;, there are only three
  possible combinations:&lt;/p&gt;
&lt;p&gt;&lt;img alt="Combinations with the ace of *golds*" src="https://www.thediligentdeveloper.com/un_oro.png"&gt;&lt;/p&gt;
&lt;p&gt;So every 3 times we bet, we will win once, so we will earn 4€ for every
  3€ we bet! Then we tell our friend: &lt;strong&gt;I want to play&lt;/strong&gt;!&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Similarly, after dealing again, the friend suggests:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Proposal #3&lt;/strong&gt;. &amp;mdash;&lt;strong&gt;Now you have the ace of &lt;em&gt;spades&lt;/em&gt;, wanna play?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="" class="mostra-solucio-parent-next"&gt;Show answer&lt;/a&gt;&lt;/p&gt;
&lt;div class="solucio"&gt;
&lt;p&gt;This case is equivalent to the one before, so we will also play!
  Having the ace of &lt;em&gt;spades&lt;/em&gt;, there are only three possible choices:&lt;/p&gt;
&lt;p&gt;&lt;img alt="Combinations with the ace of *spades*" src="https://www.thediligentdeveloper.com/una_espasa.png"&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;h4&gt;The paradox&lt;/h4&gt;
&lt;p&gt;Finally, our friend reveals the paradox:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&amp;mdash;When I tell you that you have the ace of &lt;em&gt;golds&lt;/em&gt; or the ace of &lt;em&gt;spades&lt;/em&gt;
you decide to play. However, when I tell you that you have an ace (without specifying
which one of them), you don't want to play. But it is obvious that if you have an ace
you will have either the ace of &lt;em&gt;golds&lt;/em&gt; or the ace of &lt;em&gt;spades&lt;/em&gt;!&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;What is the explanation of this paradox?&lt;/p&gt;
&lt;p&gt;&lt;a href="" class="mostra-solucio-parent-next"&gt;Show answer&lt;/a&gt;&lt;/p&gt;
&lt;div class="solucio"&gt;
&lt;p&gt;The truth is that we were a little hasty when we bet our savings to a game
  without a thorough understanding of its probabilities.&lt;/p&gt;
&lt;p&gt;The key lies in the information our friend gives us, especially when we have
  two aces. If we have two aces, which one does he tell us that we have: the
  ace of &lt;em&gt;golds&lt;/em&gt; or the ace of &lt;em&gt;spades&lt;/em&gt;? Suppose he randomly says one of them
  and let's calculate the odds again.&lt;/p&gt;
&lt;p&gt;When our friend tells us that we have the ace of &lt;em&gt;golds&lt;/em&gt;, there are three
  possibilities:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;We have the ace of &lt;em&gt;golds&lt;/em&gt; and the three of &lt;em&gt;cups&lt;/em&gt;, with probability $\frac16$.&lt;/li&gt;
&lt;li&gt;We have the ace of &lt;em&gt;golds&lt;/em&gt; and the four of &lt;em&gt;cups&lt;/em&gt;, with probability $\frac16$.&lt;/li&gt;
&lt;li&gt;We have both aces (probability $\frac16$), and our friend chose to tell us
  that we have the ace of &lt;em&gt;golds&lt;/em&gt; (probability $\frac12$). The probability is
  $\frac16\cdot\frac12=\frac1{12}$.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img alt="Probabilities of all possible outcomes" src="https://www.thediligentdeveloper.com/solucio.png"&gt;&lt;em&gt;Probabilities
  of all possible outcomes of the game&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Thus the probability of having both aces when our friend tells us that we
  have the ace of &lt;em&gt;golds&lt;/em&gt; is:&lt;/p&gt;
&lt;p&gt;$$P=\frac{\frac1{12}}{\frac16 + \frac16 + \frac1{12}} = \frac{\frac1{12}}{\frac5{12}} = \frac15$$&lt;/p&gt;
&lt;p&gt;In short, we'd better not play in any of the cases.&lt;/p&gt;
&lt;p&gt;To understand this paradox we have had to think accurately about how the game
  develops, instead of calculating some isolated probabilities that do not
  match the real problem. Joseph Halpern presents in his book a mathematical
  framework with different measures of probability, conditioning, expectation,
  protocols, etc. and formalizes the concepts needed to tackle and solve these
  problems.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;&lt;script
              src="https://code.jquery.com/jquery-3.7.0.min.js"
              integrity="sha256-2Pmvv0kuTBOenSvLm6bvfBSSHrUJ+3A7x6P5Ebd07/g="
              crossorigin="anonymous"&gt;&lt;/script&gt;
&lt;/p&gt;
&lt;script&gt;
  $('.mostra-solucio').click(function(e) {
      /* Prevent navigation */
      e.preventDefault();

      /* Slide toggle solució */
      $(this).next().slideToggle();

      /* Toggle up/down triangle */
      var html = $(this).html();
      $(this).html(html.indexOf('▾') &gt;= 0 ?
        html.replace('▾', '▴') : html = html.replace('▴', '▾'));
  });

  $('.mostra-solucio-parent-next').click(function(e) {
      e.preventDefault();
      $(this).parent().next().slideToggle();
  });
&lt;/script&gt;</content><category term="2016-two-aces-paradox"></category></entry><entry><title>Learning Haskell</title><link href="https://www.thediligentdeveloper.com/learning-haskell.html" rel="alternate"></link><published>2016-06-15T12:00:00+02:00</published><updated>2024-11-19T10:51:50+01:00</updated><author><name>Víctor López Ferrando</name></author><id>tag:www.thediligentdeveloper.com,2016-06-15:/learning-haskell.html</id><summary type="html">&lt;p&gt;Haskell is a &lt;em&gt;functional programming&lt;/em&gt; language, very different to the
programming languages ​​I'm used to (C++, Python, JavaScript...). I've been
hearing about Haskell for a while; people emphasize its elegance, its
mathematical inspiration and foundation, and the fact that being based on such a
different paradigm with respect to imperative …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Haskell is a &lt;em&gt;functional programming&lt;/em&gt; language, very different to the
programming languages ​​I'm used to (C++, Python, JavaScript...). I've been
hearing about Haskell for a while; people emphasize its elegance, its
mathematical inspiration and foundation, and the fact that being based on such a
different paradigm with respect to imperative programming &lt;a href="http://www.cs.utexas.edu/users/EWD/OtherDocs/To%20the%20Budget%20Council%20concerning%20Haskell.pdf" target="_blank"&gt;it helps thinking
about programming from a very different
perspective&lt;/a&gt;.
Python, Java, C++... are all languages ​​that are incorporating concepts from
functional programming to their latest versions. Therefore I was willing to
learn some Haskell.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Haskell logo" src="https://www.thediligentdeveloper.com/lopezferrando/2016-learning-haskell/haskell.png"&gt;
&lt;em&gt;Haskell logo&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;Material&lt;/h2&gt;
&lt;p&gt;I began to look for books, tutorials, presentations, etc. For me, the best book
for beginners is &lt;a href="http://learnyouahaskell.com/chapters" target="_blank"&gt;Learn You a Haskell for Great
Good!&lt;/a&gt;. &lt;a href="http://www.decharlas.uji.es/es/programacion-funcional-introduccion-haskell" target="_blank"&gt;This
presentation&lt;/a&gt;
(in Spanish) by UJI professor Andrés Marzal is also very interesting and
entertaining (in two hours and a half he starts presenting Haskell and ends up
explaining some pretty advanced features), it also includes some great &lt;a href="https://dl.dropboxusercontent.com/u/18532990/Haskell.pdf?utm_source=tr.im&amp;amp;utm_medium=www.decharlas.uji.es&amp;amp;utm_campaign=tr.im%2F0CIDU&amp;amp;utm_content=link_click" target="_blank"&gt;pdf
notes&lt;/a&gt;.
I also checked the book &lt;a href="http://book.realworldhaskell.org/" target&gt;Real World
Haskell&lt;/a&gt;, which I don't
think is the best book to start with, but it surely has very interesting
information if you want to develop larger projects.&lt;/p&gt;
&lt;h2&gt;Practice with... the Judge!&lt;/h2&gt;
&lt;p&gt;Once I was convinced of the benefits of Haskell, I wanted to start writing some
code, but did not have any project in mind. That's when I thought of learning
Haskell the same way I had learned to program in C++ many years ago: with &lt;strong&gt;the
Judge&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Jutge.org" src="https://www.thediligentdeveloper.com/lopezferrando/2016-learning-haskell/jutge.png"&gt; &lt;em&gt;The Judge with the classic traffic light:
green or red depending on whether your program is correct or not.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;The &lt;a href="https://jutge.org/" target="_ blank"&gt;Judge&lt;/a&gt; is a platform to learn how to
program, developed by professors Jordi Petit and Salvador Roura at UPC. This
platform contains problems to be solved by programs that are sent to the same
Judge, which automatically checks whether their execution is correct. The Judge
is used in many UPC programming and algorithms courses and &lt;strong&gt;its use is open to
the public&lt;/strong&gt;, even more... &lt;strong&gt;it contains 33 problems of a Haskell programming
course&lt;/strong&gt;!&lt;/p&gt;
&lt;p&gt;Thus, in recent weeks I have done these 33 problems :-). It has been a very
fun experience and a great excercise to get familiar with the language and
the development environment.&lt;/p&gt;
&lt;h2&gt;Haskell examples&lt;/h2&gt;
&lt;p&gt;Next I'll show some Haskell features to give an idea of its potential. These
concepts are explained in more depth in &lt;a href="http://learnyouahaskell.com/chapters" target="_blank"&gt;Learn You a Haskell for Great
Good!&lt;/a&gt;, here I will
present them together with some code examples.&lt;/p&gt;
&lt;p&gt;Working in Ubuntu, you can install &lt;code&gt;haskell-platform&lt;/code&gt; (&lt;code&gt;sudo apt-get install
haskell-platform&lt;/code&gt;) and use the &lt;code&gt;ghci&lt;/code&gt; interpreter. You can save the programs in
files (e.g. &lt;code&gt;prog.hs&lt;/code&gt;), defining in them the funtions you want. Then, these
functions can be loaded (and reloaded) with &lt;code&gt;ghci&amp;gt;: l to prog&lt;/code&gt;, which makes
them available to be used and tested.&lt;/p&gt;
&lt;p&gt;Let's see which are these interesting Haskell functionalities...&lt;/p&gt;
&lt;h3&gt;Recursion&lt;/h3&gt;
&lt;p&gt;Haskell, as a functional programming language, doesn't have loops: no &lt;code&gt;while&lt;/code&gt;,
no &lt;code&gt;for&lt;/code&gt;. One way to implement what could be done using loops is through
recursion. An example with the factorial function:&lt;/p&gt;
&lt;p&gt;$$factorial(n) = n! = n\cdot (n-1)\cdots2\cdot 1$$&lt;/p&gt;
&lt;p&gt;Recursively, we could define it as:&lt;/p&gt;
&lt;p&gt;$$\begin{cases}
factorial(0) = 1 \\
factorial(n) = n\cdot factorial(n-1)
\end{cases}$$&lt;/p&gt;
&lt;p&gt;And in Haskell, it could be implemented as follows:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nf"&gt;factorial&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;::&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;Integer&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;Integer&lt;/span&gt;
&lt;span class="nf"&gt;factorial&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="nf"&gt;factorial&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;factorial&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The first line is the &lt;em&gt;signature&lt;/em&gt; of function, which specifies the type of the
parameter and result. In our case, we use &lt;code&gt;Integer&lt;/code&gt;, which are integer numbers
of arbitrary length.&lt;/p&gt;
&lt;h3&gt;Lists&lt;/h3&gt;
&lt;p&gt;Many programs need to work with lists of values, and Haskell offers us many
ways to do it comfortably. For example, let's see some ways to get even numbers
between 0 and 20:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kt"&gt;Prelude&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;14&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="kt"&gt;Prelude&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;filter&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;even&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;14&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="kt"&gt;Prelude&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;even&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;14&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Note the last expression, which is a &lt;em&gt;list comprehension&lt;/em&gt;, very similar to the
mathematical notation $\left\{x \; \vert \; \forall\, x \in {1,\ldots,20},\;
iseven(x)\right\}$.&lt;/p&gt;
&lt;p&gt;Using recursion and list comprehensions we can implement the &lt;strong&gt;quicksort&lt;/strong&gt;
sorting algorithm. Given a list, quicksort orders the items as follows:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Choose the first element as a &lt;em&gt;pivot&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;Build two lists: the first with elements smaller than the pivot, and the
second with elements bigger than the pivot.&lt;/li&gt;
&lt;li&gt;Sort these two lists using the same quicksort algorithm.&lt;/li&gt;
&lt;li&gt;The result is a list containing the sorted smaller values, followed by the
pivot, followed by the sorted list of bigger values.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The Haskell implementation of this algorithm can be very neat:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nf"&gt;qsort&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;::&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="nf"&gt;qsort&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;[]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;[]&lt;/span&gt;
&lt;span class="nf"&gt;qsort&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="kt"&gt;:&lt;/span&gt;&lt;span class="n"&gt;xs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;=&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;qsort&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;xs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;qsort&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;xs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Lazy evaluation&lt;/h3&gt;
&lt;p&gt;Haskell is based entirely on the &lt;em&gt;lazy evaluation&lt;/em&gt;, ie, making the calculations
as late as possible, and that's when they are needed by someone else. This
enables the language to use endless lists, because values of the ​​list are
only calculated when another task needs them. For example:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kt"&gt;Prelude&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;take&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="kt"&gt;Prelude&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;take&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Using this feature, we can implement the &lt;a href="https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes" target="_blank"&gt;sieve of Eratosthenes&lt;/a&gt;
algorithm, which generates the list of prime numbers.&lt;/p&gt;
&lt;p&gt;The sieve of Eratosthenes begins with number 2 (which is prime) and marks all
its multiples. It repeatedly takes the smallest number not marked, which is
prime because it is no a multiple of any other smaller number, and again marks
all of its multiples.&lt;/p&gt;
&lt;p&gt;This process returns all primes smaller than a given number:
obviously we can not mark &lt;em&gt;all&lt;/em&gt; even numbers, because they never end.
Moreover, what we can do is to discard all even numbers lower than 1000, for
example. Haskell, however, by using lazy evaluation, is able to work
with never ending lists and therefore allows a very simple implementation:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nf"&gt;primes&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;::&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="nf"&gt;primes&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;sieve&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kr"&gt;where&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;sieve&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="kt"&gt;:&lt;/span&gt;&lt;span class="n"&gt;xs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;sieve&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;xs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;`&lt;/span&gt;&lt;span class="n"&gt;mod&lt;/span&gt;&lt;span class="p"&gt;`&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;We save it in the file &lt;code&gt;primes.hs&lt;/code&gt; and we can run:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ghci&lt;/span&gt;
&lt;span class="kt"&gt;GHCi&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;7.6&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="kt"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="kt"&gt;://&lt;/span&gt;&lt;span class="n"&gt;www&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;haskell&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;org&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;ghc&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kt"&gt;:?&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;help&lt;/span&gt;

&lt;span class="kt"&gt;Prelude&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;:&lt;/span&gt;&lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;primes&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kr"&gt;of&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;Compiling&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;Main&lt;/span&gt;&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;primes&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;interpreted&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kt"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;modules&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;loaded&lt;/span&gt;&lt;span class="kt"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;Main&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;

&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="kt"&gt;Main&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;take&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;primes&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="kt"&gt;Main&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;takeWhile&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;primes&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;13&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;17&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;19&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;23&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;29&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;31&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;37&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;41&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;43&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;47&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Higher order functions&lt;/h3&gt;
&lt;p&gt;Higher order functions are functions that take other functions as parameters.
An example is the &lt;code&gt;map&lt;/code&gt; function, which takes a function as the first parameter
and a list as the second parameter, and it applies the function to each item in
the list. For example:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kt"&gt;Prelude&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;14&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="kt"&gt;Prelude&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;^&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;36&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;49&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;81&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Given a list of integers, and a list of exponents, we can raise each number
to the given power:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kt"&gt;Prelude&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;zipWith&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;^&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;27&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;256&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;3125&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="http://learnyouahaskell.com/higher-order-functions" target="_blank"&gt;Here&lt;/a&gt;
You can find more examples of higher order functions and their use.&lt;/p&gt;
&lt;h3&gt;Pattern matching&lt;/h3&gt;
&lt;p&gt;Another interesting feature of Haskell is &lt;em&gt;pattern matching&lt;/em&gt;. We can check the
pattern &lt;code&gt;(x:y:xs)&lt;/code&gt; over a list, so &lt;code&gt;x&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt; represent the first and second
value of the list and &lt;code&gt;xs&lt;/code&gt; the remaining elements.&lt;/p&gt;
&lt;p&gt;Let us see how we can use pattern matching to implement binary tree traversal
in different orders. Let's remember first preorder, inorder and postorder
traversals:&lt;/p&gt;
&lt;p&gt;&lt;img alt="Tree traversal: preorder, inorder and postorder" src="https://www.thediligentdeveloper.com/lopezferrando/2016-learning-haskell/arbres.png"&gt; *
Ways to traverse a binary tree: preorder (left: F, B, A, D, C, E, G, I, H)
inorder (center: A, B, C, D, E, F, G, H, I) and postorder (right: A, C, E, D,
B, H, I, G, F). The black dots indicate at what time of the route each node is
chosen*&lt;/p&gt;
&lt;p&gt;And that we can implement it like this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kr"&gt;data&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;Tree&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;Node&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Tree&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Tree&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;Empty&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kr"&gt;deriving&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Show&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nf"&gt;preOrder&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;::&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;Tree&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="nf"&gt;preOrder&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;Empty&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;[]&lt;/span&gt;
&lt;span class="nf"&gt;preOrder&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Node&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;t1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;t2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;preOrder&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;t1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;preOrder&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;t2&lt;/span&gt;

&lt;span class="nf"&gt;postOrder&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;::&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;Tree&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="nf"&gt;postOrder&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;Empty&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;[]&lt;/span&gt;
&lt;span class="nf"&gt;postOrder&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Node&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;t1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;t2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;postOrder&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;t1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;postOrder&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;t2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="nf"&gt;inOrder&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;::&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;Tree&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="nf"&gt;inOrder&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;Empty&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;[]&lt;/span&gt;
&lt;span class="nf"&gt;inOrder&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Node&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;t1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;t2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;inOrder&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;t1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;inOrder&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;t2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The expressions &lt;code&gt;(Node n t1 t2)&lt;/code&gt; is where pattern matching takes place.&lt;/p&gt;
&lt;h3&gt;Input / output&lt;/h3&gt;
&lt;p&gt;Consider also a small example of input/output: a program that reads the name
a person says &lt;code&gt;Hello maca&lt;/code&gt; if the name ends in &lt;code&gt;a&lt;/code&gt; and &lt;code&gt;Hello maco&lt;/code&gt;
otherwise (maco and maca mean pretty in Catalan :P):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;::&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;IO&lt;/span&gt;&lt;span class="nb"&gt;()&lt;/span&gt;
&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kr"&gt;do&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;getLine&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;putStrLn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;$&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Hola mac&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kr"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;elem&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;last&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;aA&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kr"&gt;then&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;a&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kr"&gt;else&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;o&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;!&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Product of polynomials with Fast Fourier Transform&lt;/h3&gt;
&lt;p&gt;Finally, let's see the implementation of polynomial multiplication using the
Fast Fourier Transform. The product of polynomials of degree $n$ has a cost of
$\mathcal{O}(n^2)$ if we use the trivial algorithm: we multiply each coefficient of the
first polynomial by each coefficient of the second polynomial, and then add
them as needed, which leads to a quadratic performance. There is a much faster
algorithm with a performance of $\mathcal{O}(n\log n)$, which uses the &lt;a href="https://en.wikipedia.org/wiki/Fast_Fourier_transform" target="_blank"&gt;Fast Fourier
Transform&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;A very good explanation of how this algorithm works and how to implement it can
be found
&lt;a href="http://www.cs.cmu.edu/afs/cs/academic/class/15451-s10/www/lectures/lect0423.txt" target="_blank"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Next I show a working implementation, where the FFT is implemented in only 12
lines of code and 10 more lines are used to implement polynomial multiplication.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kr"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;Data.Complex&lt;/span&gt;

&lt;span class="nf"&gt;fft&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;::&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;Complex&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;Double&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;Complex&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;Double&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;Complex&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;Double&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="nf"&gt;fft&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kr"&gt;_&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="nf"&gt;fft&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;zipWith&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;f_even&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;zipWith&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ws1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;f_odd&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="n"&gt;zipWith&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;f_even&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;zipWith&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ws2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;f_odd&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kr"&gt;where&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="c1"&gt;-- Take even and odd coefficients of a(x)&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;a_even&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;fst&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;filter&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;even&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;snd&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;zip&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;a_odd&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="ow"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;fst&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;filter&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;odd&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;snd&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;zip&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="c1"&gt;-- Compute FFT of a_even(x) and a_odd(x) recursively&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;f_even&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;fft&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a_even&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="o"&gt;^&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;f_odd&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="ow"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;fft&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a_odd&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="o"&gt;^&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="c1"&gt;-- Compute 1st and 2nd half of unity roots (ws2 = - ws1)&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;ws1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;take&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;`&lt;/span&gt;&lt;span class="n"&gt;div&lt;/span&gt;&lt;span class="p"&gt;`&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;iterate&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;ws2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;negate&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ws1&lt;/span&gt;

&lt;span class="c1"&gt;-- Multiplication of polynomials: c(x) = a(x) · b(x)&lt;/span&gt;
&lt;span class="c1"&gt;--     * a(x) and b(x) have degree n (power of 2), c(x) has degree 2n&lt;/span&gt;
&lt;span class="c1"&gt;--   Algorithm:&lt;/span&gt;
&lt;span class="c1"&gt;--     1. Compute f_a = fft(a), f_b = fft(b)  .. O(n·logn)&lt;/span&gt;
&lt;span class="c1"&gt;--     2. Compute product: f_c = f_a · f_c    .. O(n)&lt;/span&gt;
&lt;span class="c1"&gt;--     3. Interpolate c: c = fft^{-1}(f_c)    .. O(n·logn)&lt;/span&gt;
&lt;span class="nf"&gt;mult&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;::&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;Double&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;Double&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;Double&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="nf"&gt;mult&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;[]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kr"&gt;_&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;[]&lt;/span&gt;
&lt;span class="nf"&gt;mult&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;realPart&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kr"&gt;where&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;exp&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pi&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;:+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;fromIntegral&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;f_a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;fft&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;:+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;replicate&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;f_b&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;fft&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;:+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;replicate&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;f_c&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;zipWith&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;f_a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;f_b&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fromIntegral&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;fft&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;f_c&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;To test this program, save it in the file &lt;code&gt;fft.hs&lt;/code&gt;, open a Haskell interpreter
&lt;code&gt;ghci&lt;/code&gt; and load the program: &lt;code&gt;:l fft.hs&lt;/code&gt;. We can multiply polynomials with
&lt;code&gt;mult [2,1] [3,-2]&lt;/code&gt;. Because we are working with floating point numbers, we can
see small inaccuracies (eg. instead of &lt;code&gt;2.0&lt;/code&gt;, the system can save
&lt;code&gt;1.9999999999999996&lt;/code&gt;). That's why we define &lt;code&gt;round2&lt;/code&gt;, a function which rounds
numbers to two decimal places. Here are some examples:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ghci&lt;/span&gt;
&lt;span class="kt"&gt;GHCi&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;7.6&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="kt"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="kt"&gt;://&lt;/span&gt;&lt;span class="n"&gt;www&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;haskell&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;org&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;ghc&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kt"&gt;:?&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;help&lt;/span&gt;

&lt;span class="kt"&gt;Prelude&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;:&lt;/span&gt;&lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;fft&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hs&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kr"&gt;of&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;Compiling&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;Main&lt;/span&gt;&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;fft&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;interpreted&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kt"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;modules&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;loaded&lt;/span&gt;&lt;span class="kt"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;Main&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;

&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="kt"&gt;Main&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kr"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;round2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fromInteger&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;round&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;

&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="kt"&gt;Main&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;round2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;mult&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;6.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;2.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="kt"&gt;Main&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;round2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;mult&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;6.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;2.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="kt"&gt;Main&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;round2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;mult&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;3.5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;3.5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;12.25&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;14.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;46.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;17.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;32.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;12.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="kt"&gt;Main&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;round2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;mult&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;2.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;3.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;4.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;5.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;6.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;7.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;8.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</content><category term="2016-learning-haskell"></category></entry></feed>