James Bowen James Bowen

Making the Jump to Real World Haskell

Last week, we announced our Practical Haskell course. Enrollments are still open, but not for much longer! They will close at midnight Pacific time on Wednesday, March 11th, only a couple days from now!

I've always hoped to provide content that would help people make the jump from beginners to seasoned Haskell developers. I want to show that Haskell can be useful for "Real World" applications. Those are the main goals of this course. So in this article, I wanted to share some of the mistakes I made when I was trying to make that jump. These are what motivated me to make this course, so I hope you can learn from them.

Package Management is Key

My Haskell career started with a side project, one you can still see on Github. There were some cool things about the project, but my process had several flaws. The first one was that I had no idea how to organize a Haskell project.

My early work involved writing all my code in .hs source files and running manual tests with runghc. Installing dependencies was a mess (I put everything in the global package database). I eventually learned to use Cabal, but without sandboxing. Dependency hell ensued. It was only after months of working through that process that I learned about Stack. Stack made everything easier, but I could have used it from the start!

Don't repeat my mistake! Learn how to use Stack, or just Cabal, or even Nix! This will solve so many of your early problems. It will also streamline the rest of your development process. Speaking of...

Test First, Integrate Completely

When it comes to making a project, the first question you should ask is, "How will my customer use this?" When it comes to writing code within that project, you should always then ask, "How will I know this code works?"

These two questions will guide your development and help avoid unnecessary rework. It's a natural tendency of developers that we want to jump in on the "meat" of the problem. It's exactly the mistake I made on that first project. I just wanted to write Haskell! I didn't want to worry about scripting or package non-sense. But these issues will ultimately get in the way of what you really want to do. So it's worth putting in the effort to overcome them.

The first step of the project as a whole should be to build out your end-to-end pipeline. That is, how will you put this code out there on the web? How will someone end up using your code? There will often be tedious scripting involved, and dealing with services (CI, AWS, etc.). But once that work is out of the way, you can make real progress.

Then when developing a particular component, always know how you'll test it. Most often, this will be through unit testing. But sometimes you'll find it's more complicated than that. Nothing's more frustrating than thinking you're done coding and finding problems later. So it's important to take the time to learn about the frameworks that let you test things with ease. Keep practicing over and over again until testing is second nature.

Start Simple

Another important thing when it comes to the learning process is knowing how to start small. I learned this over the course of my machine learning series last fall. My methods were often so ineffective that I didn't know if the algorithm I was trying to implement worked at all. But the problem I was trying to solve was too difficult! I've found more success in machine learning by starting with simpler problems. This way, you'll know the general approach works, and you can scale up accordingly.

This also makes it much easier to follow the advice above! If your system is large and complicated, the scripting and running process will be harder. You'll have to spend more time getting everything up and running. For a smaller project, this is not so difficult. So you'll get valuable practice at a smaller scale. This will make bigger projects smoother once you get there.

Use Both Documentation and Examples

None of us were born knowing how to write Haskell. The first time you use a library, you won't know the best practices. The documentation can help you. It'll list everything you need, but often a lot more. It can be hard to know what's necessary and what's not.

So another great thing to do when starting out is to find a project that has used the library before. You need to establish some baseline of "something that works". This way, you'll have a more solid foundation to build on. You'll have specific examples to work from, which will help build your "end-to-end experience".

In my first project, I used the Parsec library without using any examples! My code was sloppy and repetitive. There were many shortcuts I didn't know about hiding in the docs. And I could have avoided that if I had first looked for a project that also used the library. Then I could have started from there and built my knowledge.

Documentation and examples work in tandem with each other. If you use the docs without examples, you'll miss a lot of shortcuts and practical uses. If you use examples without the docs, you'll miss the broader picture of what else you can do! So both are necessary to your development as a programmer.

Conclusion

Haskell has developed a lot in the last few years, so this is a great time to learn what the language is capable of! Our Practical Haskell course aims to help you become a more seasoned developer. It'll help you avoid all the mistakes I outlined in this article. So if you've got the basics down and want to learn more, this is your chance!

And if you're not as confident in your skills yet, you can also check out our Beginners course! It requires no experience and will walk you through the basics!

Read More
James Bowen James Bowen

Taking a Look Back: My Mistakes in Learning Haskell

mistakes.jpg

Last week, we announced our Haskell From Scratch Beginners Course. Course sign-ups are still open, but not for much longer! They will close at midnight Pacific time on Wednesday, August 29th!

The course starts next week. But before it does, I wanted to take this opportunity to tell a little bit of the story of how I learned Haskell. I want to share the mistakes I made, since those motivated me to make this course.

My Haskell History

I first learned Haskell in college as part of a course on programming language theory. I admired the elegance of a few things in particular. I liked how lists and tuples worked well with the type system. I also appreciated the elegance of Haskell’s type definitions. No other language I had seen represented the idea of sum types so well. I also saw how useful pattern matching and recursion were. They made it very easy to break problems down into manageable parts.

After college, I had the idea for a code generation project. A couple college assignments had dealt with code generation. So I realized already knew a couple Haskell libraries that could provide the foundation for the work. So I got to work writing up some Haskell. At first things were quite haphazard. Eventually though, I developed some semblance of test driven development and product organization.

About nine months into that project, I had the great fortune of landing a Haskell project at my day-job. As I ramped up on this project, I realized how deficient my knowledge was in a lot of areas. I realized then a lot of the mistakes I had been making while learning the language. This motivated me to start the Monday Morning Haskell blog.

Main Advice

Of course, I’ve tried to incorporate my learnings throughout the material on this blog. But if I had to distill the key ideas, here’s what they’d be.

First, learn tools and project organization early! Learn how to use Stack and/or Cabal! For help with this, you can check out our free Stack mini-course! After several months on my side project, I had to start from scratch to some extent. The only “testing” I was doing was running some manual executables and commands in GHCI. So once I learned more about these tools, I had to re-work a lot of code.

Second, it helps a lot to have some kind of structure when you’re first learning the language. Working on a project is nice, but there are a lot of unknown-unknowns out there. You’ll often find a “solution” for your problem, only to see that you need a lot more knowledge to implement it. You need to have a solid foundation on the core concepts before you can dive in on anything. So look for a source that provides some kind of structure to your Haskell learning, like a book (or an online course!).

Third, let’s get to monads. They’re an important key to Haskell and widely misunderstood. But there are a couple things that will help a lot. First, learn the syntactic patterns of do-syntax. Second, learn how to use run functions (runState, runReaderT, etc.). These are how you bring monadic expressions into the rest of your code. You can check out our Monads Series for some help on these ideas. We’ll also have an article on this topic next week! (And of course, you’ll learn all about monads in Haskell From Scratch!)

Finally, ask for help earlier! I still don’t plug into the Haskell network as much as I should. There are a lot of folks out there who are more than willing to help. Freenode is a great place, as is Reddit and even Twitter!

Conclusion

There’s never been a better time to start learning Haskell! The language tools have developed a ton in the last few years and the community is growing stronger. As we announced last week, we’ve now opened up our Haskell From Scratch Beginners Course! You don’t need any Haskell experience to take this course. So if you always wanted to learn more about the language but needed more organization, this is your chance!

Read More
James Bowen James Bowen

BayHac 2018!

BayHac.png

This week we’ll be taking a quick breather from our work on deploying our Haskell code. Instead, I’ll be giving a brief overview of BayHac, the Bay Area Haskell Hackathon, which took place a week ago from April 27-29. It was hosted once again by Formation (formerly Takt). Many Haskellers from the Bay Area and beyond met up, hacked and discussed many ideas.

Presentations

This year there was a larger focus on projects and hacking, and less on presentations. But there were still a few short talks each morning. I was only able to make one set of these, but that included some very interesting topics. A couple speakers discussed some of the theoretical aspects of Haskell’s containers. One went through the idea of free objects, a generalization of free monads as seen on this blog. Another speaker discussed ways to perform type-level validation within Postgres.

And speaking of databases, Travis Athougies gave an overview of his Beam database library. This library has some awesome semantics. It might force me to re-think my habit of defaulting to Persistent, so it's definitely worth a look!

Finally, I gave a short overview of some of the work I did last year with Tensorflow and dependent types. I’ll post a link to the presentation as soon as it’s up. But in the meantime, you can check out the full blog series to learn more!

Nix and HNix

I spent most of my time at the Hackathon trying to setup Nix, so that I could work on HNix. Nix is a functional package manager with incredible reliability. We could use it for any language in theory. But it shares many conceptual ideas with Haskell, so many Haskellers have adopted it. In particular, if you do frontend web programming with GHCJS, you’ll want to use Nix instead of Stack.

Several people at the Hackathon worked on HNix, a Haskell implementation of Nix. The work was well organized by John Wiegley. He put in a lot of time parceling out tasks that newcomers could contribute to the codebase.

Having a Windows laptop, I wasn’t able to contribute a whole lot to the project (Nix only runs on *nix systems). Instead, I let myself be a guinea pig to see if I could get Nix working on the Windows Subsystem for Linux. My efforts were unsuccessful, though Jonas Chevalier of Tweag insists it’s possible.

Codeworld

The last talk I saw came from Chris Smith, who gave an overview of Haskell Codeworld, an educational tool for math and programming. This project in particular caught my attention for a couple reasons. First, I’ve developed a passion for teaching Haskell to beginners and showing it’s not so hard. But even I tend not to focus on teaching Haskell as a first language. Chris’s idea is to teach Haskell to middle school kids who have never written code before.

His primary intention is to teach mathematics. Since Haskell has such a mathematical view of programming, it's a natural fit. He stated an interesting finding from an academic study. Children’s success in calculus depends a lot on their understanding of functions. Those who view functions as a mere series of steps to compute tend to struggle. But there's another more correct way to view functions. This idea is that functions express a fundamental relationship between sets. Those who view functions this way have a better chance of flourishing.

This research suggests Haskell is great as a primary programming language for kids! It matches the latter definition, while object oriented languages teach the former idea. Codeworld a cool project, so check it out and see if you can help in any way!

Conclusion

Next week, we’ll conclude our series on deploying Haskell code by looking at Github’s API. It has some neat little tricks we can play to enhance our development experience.

Events like BayHac show that there are a lot of different ways to get involved in the Haskell community. See if you can find one in your city! And don’t worry if you’ve never written Haskell before! The Haskell community is very welcoming! Check out our Beginners Checklist to get started!

Read More
James Bowen James Bowen

1 Year of Haskell

This week marks the one year anniversary of Monday Morning Haskell! I’ve written an awful lot in the past year. It’s now obvious that the “blog” format doesn’t do justice to the amount of content on the site. There’s no organization, so a lot of the most useful content is stuck way down in the archives. So I’m taking this opportunity to announce some plans to reorganize the website!

Website Organization

I have two main focuses when it comes to Haskell. First, making the language easier for beginners to pick up. Second, showing the many industrial-strength tasks we can perform with Haskell. There will be two different sections of the website highlighting these components.

There will be a beginner’s corner that will focus on giving advice for starting the language from the ground up. It will feature content about the fundamental concepts and techniques of the language. It will also showcase some advice for conquering the psychological hurdles of Haskell. There will also be a section devoted to articles on production libraries, such as the recent series on building a Web API and using Tensor Flow.

Future Posts

This means I'll be focusing on organizing permanent content for a while. As a result, I won’t have as much time to spend on new blog posts. But I will still be publishing something new every Monday morning! These new posts will focus on distilling concepts into the most important parts. They'll look back at earlier lessons and pick out the highlights. Of course, I still have plans for some more in-depth technical tutorials. I’ll be looking at areas such as front-end web development, creating EDSLs, the C foreign function interface, and more.

Academy

I also am working hard on some new course material to go with our current free mini-course on learning Stack! I'm currently working on a full-length courses beginners course to help people learn Haskell from scratch. I will follow that up with another course aimed at using Haskell in production. This second course will go through both generally important production skills and showcase Haskell libraries applying those skills.

Conclusion

Altogether, the fun is just beginning at Monday Morning Haskell! I’m committed to continuing to build this website to be a resource for beginners and experts alike!

If you’re a beginner yourself, check out any of our newbie resources, like our Getting Started Checklist, our Recursion workbook, or the Stack mini-course mentioned above!

Read More
James Bowen James Bowen

The Right Types of Assumptions

A little while back I was discussing my Haskell and AI article with some other engineers I know. These people are very smart and come from diverse backgrounds of software engineering. But they tend to prefer dynamically typed languages like Javascript and Ruby. So they don’t buy into Haskell, which makes them no different from most of the engineering community.

Still, some things about the discussion surprised me. I heard, of course, the oft-repeated mantra that types do not replace tests. But even more surprising was one claim that types do not, and are not even meant to provide any kind of safety. One engineer even claimed he thinks of types only as directives to help a compiler optimize a program.

Now, it would be bold to claim that Haskell is better for all things and all circumstances. But I don’t think I’ve ever done that on this blog. It would also be unrealistic to claim that Haskell’s type system can replace all testing. And in fact I’ve dismissed that claim a couple times on this blog.

But surely Haskell’s type system gets us something. Surely, compiled types add some layer of extra safety and correctness to our programs. I’ve never thought this to be a particularly controversial point. Any yet many smart people dismiss even this claim. So these conversations got me thinking, why is it that I think Haskell's type system is useful? Why do I believe what I do?

Convincing Myself

For me, the evidence is a matter of personal experience. And a lot of other Haskellers would agree. I programmed in dynamic languages, such as Python and Javascript. I’ve also dealt a lot with Objective C and Java, which have static types but do not restrict effects as Haskell does.

It’s very clear to me where I get fewer bugs and write cleaner code that is more often correct, and that’s with Haskell. But of course I can’t base everything on my own experience, which could be subject to many biases. For instance, it could be that I haven’t spent enough time writing in dynamic languages at an industry level. It could also be that I happen to have become a more competent programmer in the last year. Perhaps I would have seen similar improvements no matter what language I focused on. Still, Haskell changed my programming in ways that other languages wouldn't have. I feel I could now go back to other languages and write better programs than I could before I learned Haskell.

Regardless, I would not feel as confident. Without Haskell's guarantees, there’s a great deal more mental overhead. You have to always ask yourself questions like, is every error condition checked? Are all my values non-null? Have I written enough tests to cover basic data format cases? Have I prevented effects like slow-running DB operations in performance critical places? Determining the answers to these might require a line-by-line audit of the code. Thorough code review is good. But when it becomes a pain, corners will get cut.

Perhaps if I had a couple more years experience writing Javascript, I wouldn’t view these tasks as such a burden. But one of the best answers I ever read on Quora gave this piece of advice. As you become a better programmer, you don’t get better at keeping things in your head and knowing the whole system. You get better at sectioning off the system in a way that you don’t have to keep it in your head. Haskell lends itself very well to this approach.

So it’s true that other languages can be written in a safe way. But Haskell forces you to write and think safely. In this regard, Haskell would actually be a fantastic first language.

Empirical Evidence?

Now there’s been some efforts to study the effects of programming language choice. This dissertation from UC Davis examined many open-source code bases to find what factors led to fewer bugs. The conclusion, was that strongly typed, functional languages fare better. A much older paper from Yale found that Haskell was a clear winner when it came to code clarity. (Python and Javascript weren’t covered in the study though).

Case closed right?

Well of course not. With the UC Davis paper, many possible issues prevent firm conclusions. After all, it only studied open source code and not industrial code. Confounding factors might well exist. Functional projects could just have fewer users. This could explain fewer bug reports. Also, code size dwarfed any effects of language choice. More code = more bugs.

But it’s hard to see how we could settle this question with an empirical study. No one has access to programmers with arbitrary levels of experience in a language. The Yale paper might have had the right idea. But it would need a larger scale to draw more solid conclusions.

What Other Evidence is out there?

So failing this kind of assessment, what is the best way to provide evidence in Haskell’s favor? It’s rather hard to look past testimony here. It would be great to see more publicity around stories like at Channable. Engineers there were able to use convert a small piece of infrastructure to Haskell. The result was a system that had fewer bugs that they could refactor with confidence.

Of course, testimony like this is still imperfect. There could be major survivorship bias. For every person who posts about Haskell solving their problems, there may be 5 who found it didn't help.

There’s also the fact of the world that many people don’t like change. You could provide all the evidence in the world in favor of a particular language. Some people will still choose to fall back on what they know. For people who have “tried and true” business models, this makes sense. Anything else seems risky.

So how do we Convince People?

I’ll repeat what I’ve noted a couple times in previous articles. Network effects are currently a huge drag on Haskell. The more Haskell developers who are out there, the easier it will be to convince companies to give it a try. Even if it is only on small projects, there will be more chances to see it succeed.

What is the best way to go about solving these network issues? For one, we need more marketing/Haskell evangelism. That said, there is still a sense that we need more educational material at all levels. Helping beginners get into the language is a great start. But there's definitely another hurdle to go from hobbyist to industry level.

Conclusion

Every once in awhile it’s important to take a step back and consider our assumptions. I definitely found it worthwhile to reexamine some of my beliefs about Haskell’s type system. It's helped me to remember why I think the way I do. There’s a good amount of evidence out there for Haskell’s utility and safety as a language. But the burden is on us as a community to collect those stories and put them out there more.

If you haven’t tried Haskell before, hopefully I’ve convinced you to be one of those people! Check out our Getting Started Checklist for some good resources in starting your Haskell education.

If you’ve dabbled a bit and want to make the next step up, we also have a few other resources for you! Check out of Stack mini-course, our Recursion Workbook or our Haskell Tensor Flow guide!

Read More
James Bowen James Bowen

Haskell and Deliberate Practice

Have you ever been in a situation where you tried learning something, put in the proper time, and got stuck? Chances are you weren't learning in the best way. But how can you know what constitutes good learning in your field? It can be frustrating to try to find advice for how to learn a specific topic on the internet. Most people do not think about the manner in which they learn. They do learn, but they can’t externalize and teach other people what they did, so there aren't guides for this sort of thing.

In our first article on learning, we focused on some higher level learning techniques. The aim of these was to get ourselves more learning time and motivation. But even if your macro-techniques are good, you ultimately need domain specific practice. The second article in this series showed one specific technique for learning Haskell. It's a start, but I still want to share some more general ideas.

This article will go over a couple more key ideas from The Art of Learning by Josh Waitzkin. The first concept we’ll talk about is the idea of deliberate practice. The goal of deliberate practice is to zero in on a specific idea and try to improve a certain skill until it become subconscious. The second concept is the role of mistakes in learning any new skill. We'll use these to propel ourselves forward and prevent ourselves from tripping over the same ideas in the future.

Deliberate Practice

Suppose for a moment you’re learning to play a particular piece of music on the piano (or any instrument). The biggest temptation out there is to “learn” the piece by repeatedly playing it from start to finish. You’ll get a fair amount right, and you’ll get a fair amount wrong. Eventually, you’ll get most of it right. This is a tempting method of practice for a few different reasons:

  1. It’s the “obvious” choice.
  2. It let’s us do the parts we already enjoy and are good at, which feels good.
  3. It is, after all, most like what we’ll actually end up doing in a performance.

However, it’s a suboptimal method from a learning perspective. If you want to improve your ability to play the piece from start to finish, you should focus on your weakest areas. You have to find the specific passages that you are struggling with. Once you’ve determined those, you can break them down even further. You can find specific measures or even notes that you have difficulty with. You should practice these weaknesses over and over again, fixing one small thing at a time. At a certain point, you’ll need to go all the way through, but this should wait until you’re confident on all your weak spots.

The focus on small things is the most important part. You can’t take a tricky passage you know nothing about and play it perfectly from start to finish. You might start with one section that forces you make a quick hand movement. You might practice a dozen times just focusing on getting the last note and then moving your hand. Nothing else is important for these dozen repetitions. Once you’ve made the hand movement subconscious, you can move onto another idea. The next step might be to make sure you hit the first three notes after the hand movement.

This sums up the idea of deliberate practice. We focus on one thing at a time, and practice that one thing deliberately. Mindless practice, or practice for the sake of practice will only give us slow progress. It may even impede our progress if we build up bad habits. We can apply it to any skill out there, including coding. We want to build up tiny habits that will gradually make us better.

Mistakes

So deliberate practice is a system of building up skills that we want. However, there are also plenty of habits we don’t want. We do many things that we realize later are errors. And the worst thing is when we realize we’ve made the same error over and over again!

Waitzkin notes in Art of Learning, “If a student of any disciple could avoid ever repeating the same mistake twice, they would skyrocket to the top of their field.” We could also do this if we avoid mistakes entirely, but this isn’t possible. We’ll always make mistakes the first time we try something.

So first we have to embrace the certainty that mistakes will happen. Once we’ve done this, we can have a plan for dealing with them. We won’t be able to avoid ever repeating mistakes, but we can take steps that will reduce the rate at which we do. And if we’re able to do this, we’ll see major improvement. Our solution will ultimately be to keep a record of the mistakes we make. By writing things, down, we'll dramatically reduce the repetition of errors.

Practicing Haskell

So now we need to step back into the land of coding and ask ourselves how we can apply these ideas to Haskell. What specific areas of our coding practices can we focus on? Let’s start with a couple lessons from Compile Driven Learning.

You could write an application, and focus on nothing but building the following habit: before you write a function, stub it out as undefined and make sure the type signature compiles. It doesn't matter if you do anything else right! After you've gotten into that habit, you could also take another step. You could make sure you always write the function’s invocation (where your other code calls the function) before you implement it.

I’ve chosen these examples because there are two things that slow us the most when writing functions. The first is a lack of clarity because we don’t know exactly how our code will use the function. The second is the repetition of work when we realize we need to re-write the function. This can happen because there was an extra type we didn’t account for or something like that. These habits are designed to get you to plan more up front so that your life is simpler when it comes to implementation.

Here are a couple of other ideas in a similar vein:

  1. Before writing a function, write a comment describing that function.
  2. Before you use expressions from a library, add it to your .cabal file. Then, write the import statement to make sure you are using the right dependency.

Another great practice is to know how you will test a piece of functionality before you implement it. In a couple weeks we'll explore test driven development, where we'll write test cases for our functions. But if it’s a very simple feature, like getting a line of input and parsing it in some way, you can get away with simpler ideas. You could commit to running your program on the command line with a couple types of input, for instance. As long as you know your approach before you start coding, it counts. It might be most helpful to write the test plan in some document first.

So in almost all the above cases, the “trigger” for building this habit is writing a new function. The trigger is the most important part of building a new habit. It is the action that tips your brain off that you should be doing something you’re not accustomed to doing. In this case, the trigger could be writing the :: for the type signature. Every time you do this, remind yourself of your current goal.

Here’s an idea with a different trigger. Every time you pick a structure to contain your data (list, sequence, set, map, etc.), brainstorm at least three alternatives. Once you get beyond the basics, you’ll find each structure has its unique strengths. It would be most helpful if you wrote down your reasoning for your final choice. The trigger in this case could be every time you write the data keyword. For a more extreme version, the trigger could be writing down the left bracket to start a list. Each time you do this, ask yourself if you could be using a different structure.

Here's one final possibility. Every time you make a type synonym, ask yourself if you would be better served making a newtype out of it instead. This often leads to better compile time behaviors. You'll likely see clearer error messages, and you'll catch more of your errors at compile time. The trigger here is also simple: any time you type the keyword type.

Here’s the most important thing though. Don’t try more than one of these at a time! You want to pick one thing, practice it until it becomes subconscious, and then move on to other things. This is the hardest part about deliberate practice: maintaining your patience. The biggest temptation is to move on and try new things often before the good habits are solidified. Once you shift your focus onto other items, you might lose whatever it was you were working on! Remember to treat learning like compound interest! You need to make small investments that stack up over a long period time. You can't necessarily hurry the process.

Tracking Mistakes

Let's also consider the various ways we can avoid making the same mistakes in the future. Again, these are different from the “skills” you build up with deliberate practice. They don't occur much, and you don’t want to “practice” them. You just want to remember how you fixed some issue so you can solve it again if it does come up. You should keep a list in a google doc of all the worst mistakes you’ve encountered in your programming. The google doc should record three things for each mistake.

  1. What was the compiler message or runtime behavior?
  2. What was the problem with your code?
  3. How did you fix it?

So for an example, think about a time you were certain your code was correct. You look at the error, then back to your code, then back to the error. And you're still sure your code is right. Of course, the compiler is (almost) always right. You want to document these so they don't trip you up again.

Other good candidates are those runtime errors where you cannot for the life of you track down where the error even occurred in your code. You’ll want to write down what this experience was like so the next time it happens, you’ll be able to fix it quickly. By writing about it, you’ll also motivate yourself to avoid it as well.

Then there are also dumb mistakes that you should record because it’ll teach you the right way faster. Like when you’re starting out you might use the (+) operator to try to append two strings instead of the (++) operator. By writing down errors like this, you'll learn quirky language features much faster.

One final group of things you should track down is awesome solutions. Not just bug fixes, but solutions to your central programming problems. For instance, you found your program was too slow, but you used a better data structure to improve it. Not only does it feel good to write about things that went well, you’ll have a record of what you did. That way, you’ll be able to apply it next time as well. These kinds of items (both the good and the bad) make good fodder for technical interviews. Interviewers are often keen to see what kinds of challenges you’ve overcome to show your growth potential as an engineer.

I have one example that demonstrates the good and bad of recording mistakes. I had a nasty bug when I was trying to build my Haskell project using Cabal. I remember it being a linker error that didn’t point to any particular file. I did a good job in making a mental note that the solution was to add something to the “.cabal” file. But I didn’t write down the full context or full solution. So in the future, I'll see a linker error and know I have to do something in the “.cabal” file, but I won’t be sure exactly what. So I’ll still be more likely to repeat this error than I would if I had written down the full resolution.

Summary

It’s an oft-repeated mantra that practice makes perfect. But as anyone who’s mastered a skill can tell you, only good practice makes perfect. Bad or mindless practice will leave you stuck. Or worse, it will ingrain poor habits that will take more time to undo. Deliberate practice is the process of solidifying knowledge by building up tiny habits. You pick one thing to focus on, and ignore everything else. Then you learn that focus until it has become subconscious. Only then do you move on to learning other things. This approach requires a great deal of patience.

One final thing we have to understand about learning is the need to embrace the possibility that we will make mistakes. Once we have done this, we can make a plan for recording those mistakes. This way, we can learn from them and not repeat them. This will dramatically improve our pace of development.

If you want start out on your journey of deliberate practice, you should download our Recursion Workbook! In addition to some content on recursion, it contains 10 practice problems. The answer start from undefined so you can build up your solutions step-by-step. It's a great way to learn deliberate practice ideas!

If you’ve never written a line of Haskell before, don’t be afraid! You should check out our Getting Started Checklist. It will walk you through installing Haskell and give you some helpful tools for starting on your Haskell journey!

Read More
James Bowen James Bowen

BayHac 2017!

I spent most of this last weekend at BayHac, the Bay Area Haskell Hackathon! It was hosted at Takt headquarters in San Francisco. I had been looking forward to the event for a long time and I was not disappointed. I had a blast and met a ton of smart, interesting people. I also got to speak at an event for the first time, which was a lot of fun.

The event had two primary sections of activity. First, there was a packed schedule of speakers talking about a wide array of topics. The talks ranged from some basic Stack usage all the way to some eye-opening category theory. Second, several open source maintainers coordinated some hacking on their projects.

Now, given the event was a “Hackathon”, I should perhaps have focused more on this second part than I did. That said, the litany of fascinating topics for the talks made this difficult. I managed a little bit in the end, but I'll start by going through my observations on the talks. A few major themes stood out. Many of my articles and posts try to highlight some of these themes. But it helps enormously to see concrete examples of these.

Language Safety

The first theme was Haskell’s safety as a language. The first talk of the event was given by Greg Horn, who discussed his work at Kittyhawk. He has been developing a flight-control system for small aircraft in Haskell. There isn’t a large margin for error when dealing with objects flying high above the ground. One small bug involving any kind of crash could be extraordinarily expensive. This is a large part of his motivation in using Haskell.

As I stress so often about Haskell, he is confident he can write and refactor Haskell code without breaking anything. Further there are even compile time guarantees that OTHER people can’t break things. His code also involved compiling Haskell code to C to run on embedded systems. But he managed to make most of his code pure. So the generated C code was a subset that excluded a lot of unsafe activities.

Needless to say, it was cool to see Haskell used on such a cool application. It’s even cooler to know that it’s not just being used for the sake of using Haskell. There are real language level concepts that distinguish Haskell and make it more suitable for certain tasks.

Expressiveness and Simplicity

Another talk came from Tikhon Jelvis. He discussed his work optimizing Target’s supply chain. His work is notable for tackling some fascinating mathematical problems involving non-deterministic probability. He managed to express complex probabilistic math within a monad. The simplicity of the final code was mind-boggling.

But another more prosaic issue also struck me as a real showcase of the power of Haskell's simpler ideas. Target’s database has a curious identification schema on their items. One object could potentially have three different identifiers. In dynamically typed languages, you'd likely be stuck using strings for them all. It can be a real pain to keep the different identifiers straight. You're likely to use the wrong one at some point. Tracking down bugs can be nigh impossible. Even if you make wrapper objects, you still likely won’t get compile time guarantees. And it’s quite possible a novice developer will be able to slip in incorrect usages.

Haskell avoids this with newtypes. We can simply wrap each type of ID in a different type. This gives us compile time guarantees that we are not comparing different ID types. This example strengthened my firm belief that even Haskell's simple concepts can give you some big advantages.

The Rise of Frontend Haskell

Takt’s trio of Luite Stegeman, Greg Hale, and Doug Beardsley (previously featured on Monday Morning Haskell!) all gave interesting talks on various topics related to front-end web development in Haskell. Luite discussed some of the intricacies of GHCJS. Doug shared some problems he had encountered over the course of using Reflex FRP, and how he’d solved them. I didn’t get a chance to catch much of Greg’s talk (though they’ll all be up online soon). But I gather from the title it involved showing how nice and easy our life can be when we use Haskell full-stack and get to use the same types everywhere!

Full-stack Haskell applications have existed for a while. But I'm very encouraged by the progress I see in the front-end community, especially with FRP. There seem to be a lot of new ideas and solutions out there. And they're constantly getting better and better. My fingers are crossed that Haskell could soon be widely considered a strong competitor as a full-stack web language.

Breaking Down the Complex

Haskell has a lot of complicated ideas. But several speakers did a great job breaking them down and showing concrete examples. There were a couple talks that accomplished this for some category theory concepts. Julie Moronuki (co-author of the Haskell Book) discussed monoids, semi-groups, and their connections to boolean algebra. Rúnar Bjarnason (co-author of this Scala Book) went into some details on adjunctions and showed how common they are.

Meanwhile Jon Wiegley and Sandy Maguire tackled a couple more concepts that are pretty high on my TODO list for learning: lenses and free monads. I’ve definitely tried learning about lenses before. But I still have little competency beyond playing “monkey see, monkey do” and copying from other examples in the codebase. But now it might have finally clicked. We’ll see. I’m a firm believer in the Feynman Technique. So you can probably expect to see a blog post on lenses from me sometime soon.

Baby’s First Talk!

Besides all these crazy smart people, BayHac also let me give a talk! I gave an introduction to the fantastic Servant library. In all the languages I have programmed in, it is the best tool I have come across for building or even calling an API. You start by describing your API as a type. Then you write your server side handlers. Once you've done this, Servant can generate a lot of other code for you. You'll get things like client side functions and documentation almost ready made. I’ll link to the video of the presentation once it’s up. But in the meantime you can check get the slides and code samples I used for the presentation. They should give you a decent taste of the Servant library so you can get started!

Tensor-Flow and Some Hacking

In the midst of all this I sort’ve managed to do something approaching “hacking”. Of the projects listed before hand, the one that stood out to me most was Haskell Tensor Flow. I've been focusing a lot on the Haskell language lately. This means I haven’t gotten much of a chance to focus on some other skills, particularly machine learning and AI. So I was super psyched at getting to learn more about this library, which allows you to use Google’s awesome Tensor Flow API from Haskell. I didn’t manage to hack much of anything together. I mostly spent my time wrapping my head around the Tensor Flow concepts and the Haskell types involved. Judah Jacobson’s presentation helped a lot in this regard. I’m hoping to learn enough about the library to start making contributions in the future.

Conclusion

So to summarize, BayHac was a fantastic event. On the plus side I learned a ton about different areas of Haskell. Meeting more people in the Haskell community was a great experience. I look forward to having more opportunities to share knowledge with others in the future. The only minus is that I now have way too many things I want to learn and not enough time. I can cope with a language that puts me in that position.

The last big takeaway from BayHac was how open and inviting the community is to newcomers. If you’ve never written a line of Haskell before, you should check out our Getting Started Checklist. It’ll walk you through installing the language and point you to some basic tools to help you on your way!

Read More
James Bowen James Bowen

Compile Driven Learning

Imagine this. You've made awesome progress on your pet project. You need to add one more component to pull everything together. You bring in an outside library to help with this component and you...get stuck. You wonder how you're supposed to get started. You take a gander at the documentation for the library. It's not particularly helpful.

While documentation for Haskell libraries isn't always great, there is a saving grace. As we’ve explored before, Haskell is strictly typed. Generally, when it compiles, it works the way we expect it to. At least this is more common in Haskell than other languages. This can be a double-edged sword when it comes to learning new libraries.

On the one hand, if you can cobble together the correct types for functions, you're well on your way to success. However, if you don't know much about the types in the library, it's hard to know where to start. What do you do if you don't know how to construct anything of the right type? You can try to write a lot of code, but then you’ll get a mountain of error messages. Since you aren’t familiar with the types, they’ll be difficult to decipher.

In this article, I'll share my approach to solving this learning problem. I refer to it as "Compile Driven Learning". To learn a new library or system, you should start out by writing as little code as you can to make the code continue to compile. It is intricately related to the ideas of test driven development. We'll go over this idea in more detail in next week's article, but here's the 10000 ft. overview.

Test Driven Development

Test driven development is a paradigm of software development where you write your tests before writing your source code. You consider the effects you want the code to have, and what the exposed functions should be. Then you write tests establishing expectations about the exposed functions. You only write the source code for a feature once you’re satisfied with the scope of your tests.

Once you’ve done this, the test results drive the development. You don’t have to spend too much time figuring out what piece of code you should implement. You find the first failing test case, make it pass, rinse and repeat. You want to write as little code as you can to make the test pass. Obviously, you shouldn't just be hard-coding function definitions to fit the tests. Your test cases should be robust enough that this is impossible.

Now, if you’re trying to write as little code as possible to make the tests pass, you might end up with disorganized code. This would not be good. The main idea in TDD to combat this is the Red-Green-Refactor cycle. First you write tests, which fail (red). Then you make the tests pass (green). Then you refactor your code to make it live up to whatever style standards you are using (refactor). When you've finished this, you move on to the next piece of functionality.

Compile Driven Learning

TDD is great, but we can’t necessarily apply it to learning a new library. If you don’t know the types, you can’t write good tests. So you can use this process instead. In a way, we’re using the type system and the compiler as a test of our understanding of the code. We can use this knowledge to try to keep our code compiling as much as possible to accomplish two goals:

  1. Drive our development and know exactly what we’re intending to implement next.
  2. Avoid the discouraging “mountain of errors” effect.

The approach looks like this:

  1. Define the function you’re implementing, and then stub it out as undefined. (Your code should still compile.)
  2. Make the smallest progress you can in defining the function so the code still compiles.
  3. Determine the next piece of code to write, whether it is an undefined value you need to fill in, or a stubbed portion of a constructor for an object.
  4. Repeat 2-3.

Notice at the end of every step of this process, we should still have compiling code. The undefined value is a wonderful tool here. It is a value in Haskell which can take on any type, so you can stub out any function or value with it. The key is to be able to see the next layer of implementation.

CDL In Practice

Here’s an example of running through this process from "One Week Apps", one of my side projects. First I defined an function I wanted to write:

swiftFileFromView :: OWAAppInfo -> OWAView -> SwiftFile
swiftFileFromView = undefined

This function says we want to be able to take an “App Info” object about our Swift application, as well as a View object, and generate a Swift file for the view. Now we have to determine the next step. We want our code to compile while still making progress toward solving the problem. The SwiftFile type is a wrapper around a list of FileSection items. So we are able to do this:

swiftFileFromView :: OWAAppInfo -> OWAView -> SwiftFile
swiftFileFromView _ _ = SwiftFile []

This still compiles! Admittedly, it is quite incomplete! But we’ve made a tiny step in the right direction.

For the next step, we have to determine what FileSection objects go into the list. In this case we want three different sections. First we have the comments section at the top. Second, we have an “imports” section. Then we have the main implementation section. So we can put expressions for these in the list, and then stub them out below:

swiftFileFromView :: OWAAppInfo -> OWAView -> SwiftFile
swiftFileFromView _ _ = SwiftFile [commentSection, importsSection, classSection]
  where
    commentSection = undefined
    importsSection = undefined
    classSection = undefined

This code still compiles. Now we can fill in the sections one-by-one instead of burdening ourselves with writing all the code at once. Each will have its own component parts, which we’ll break down further.

Using our knowledge of the FileSection type, we can use the BlockCommentSection constructor. This just takes a list of strings. Likewise, we’ll use the ImportsSection constructor for the imports section. It also takes a list. So we can make progress like so:

swiftFileFromView :: OWAAppInfo -> OWAView -> SwiftFile
swiftFileFromView _ _ = SwiftFile [commentSection, importsSection, classSection]
  where
    commentSection = BlockCommentSection []
    importsSection = ImportsSection []
    classSection = undefined

So once again, our code still compiles, and we’ve made small progress. Now we’ll determine what strings we need for the comments section, and add those. Then we can add the Import objects for the imports section. If we screw up, we’ll see a single error message and we’ll know exactly where the issue is. This makes for a much faster development process.

Summary

We talked about this approach for learning new libraries, but it’s great for normal development as well! Avoid the temptation to dive in and write several hundred lines of code! You’ll regret it when dealing with dozens of error messages! Slow and steady truly does win the race here. You’ll get your work done much faster if you break it down piece by piece, and use the compiler to sanity check your work.

If you want to take a stab at implementing Compile Driven Learning, you should check out our free Recusion Workbook! It has 10 practice problems that start out as undefined. You can try implement them yourself step-by-step and see if you can get the tests to pass!

If you’ve never written any Haskell before and want to try it out, you should read our Getting Started Checklist. It’ll tell you everything you need to know about writing your first lines of Haskell!

Finally, stay tuned for next week when we’ll go into more depth about Test Driven Development. We’ll see how we can achieve a similar effect to CDL by using test cases instead of merely seeing if our code compiles.

Read More
James Bowen James Bowen

Learning to Learn Haskell

A month or two ago, we discussed the Intimidation Factor of Haskell. That article focused on why people see Haskell as challenging and why they shouldn't. Today we’ll pick up on some of the threads of that conversation. We'll explore the how of learning Haskell (and other things). We’ll examine some general ideas on learning and discuss how to apply them to programming.

Warren Buffett and Compound Interest

There’s an oft-repeated line on productivity about Warren Buffett. He says he reads at least 500 pages a day, and this is one of the major keys to his success. Knowledge, according to Buffett, is like compound interest. The more you acquire, the more it accumulates and is able to build on itself as you make more connections.

The why of this statement is fantastic. I’ve found it rings true as I explore different topics. I have seen how my knowledge has begun building on itself. And yet, the how is often misunderstood and misinterpreted. This leads people to have a difficult time implementing Buffett's principle.

The simple fact is that the average person does not have time to read 500 pages a day. First, if he reads so much, Warren Buffett is likely an accomplished speed reader, so he needs less time. Second, he is in far more control of his time than most other people due to his wealth. In my current job as a software engineer, I cannot spend a full 80% of my working day on “reading and thinking”. I would have some very unhappy teammates and project managers to deal with.

The average person will see this advice and decide to start reading a ton outside of working hours. They might even succeed in hitting 500 pages a day...for a couple days. Then of course life gets in the way. They won’t have time over a few days to do it, and they’ll drop the habit.

A Better Application

So how do we achieve the compound knowledge effect? The real misinterpretation I find about this advice is this. The key factor in compound interest is time, not average investment. Making small, repeated contributions will have major rewards later on. Of course, big, repeated contributions will have major rewards as well. But if the investment causes us to give up the habit, we'll be worse off over time.

Once we accept this idea, we can apply it to other topics, including Haskell programing. We might be tempted to devote an hour every day to learning some particular Haskell concept. But this is often unsustainable. It is far easier to devote at least 15 minutes a day, or even 10 minutes a day. This will ensure we’re going to continue learning. On any given day, it can be hard to carve out a full hour for something. Your schedule might not allow that contiguous block of time. But you should always be able to find a 15 minute block. This will dramtically lower the barrier of starting each day, so you'll be more likely to succeed.

In keeping with the compound interest principle, progress is momentum based. By committing to 15 minutes a day on a couple different projects, I’ve made a ton of progress. I've accomplished far more than if I had tried to carve out an hour here and there. I was only able to start writing online because I devoted 20 minutes a day to writing. Once I stuck with that for a month, I was in good shape.

Josh Waitzkin and Confronting Difficulties

Another of the most important ideas about learning I’ve encountered comes from The Art of Learning, by Josh Waitzkin. He is a former chess prodigy and grandmaster turned world-champion martial artist. He describes a story that was all-too familiar to me as a fellow childhood chess player. He saw many young players with a lot of potential. They would beat everyone around them at their school or local chess club. But they never brought themselves to face stronger opposition. As a result, they ended up not improving, and ultimately quit chess. They were so invested in the idea of winning every game that losing to anyone was too much of a blow to their pride.

If we focus on our egos too much, we’ll be afraid of appearing weak. The causes us to avoid confronting the areas of our knowledge where we actually are weak. These are exactly the areas we need to strengthen! If we never address these areas, we’ll never improve, and we won't be able to beat big challenges.

Confronting Haskell

So how does this affect learning Haskell, or programming in general? After all, programming is not a competitive game. And yet, there are still ways in which this mentality can hurt us. We might stay away from a particular topic because it seems difficult. We're concerned that we'll try to learn it and fail. And we worry this failure will reveal how peculiarly unfit we are to be Haskell developers. Worse, we're afraid to ask other programmers for help. What if they look down on us for our lack of knowledge?

I have three main responses to this. First, I'll repeat a note from the intimidation article. A topic is infinitely more intimidating when you know nothing about it. Once you know even the most basic definitions, you have a reasonable idea of what you're missing. Get as basic an idea of it as you can and write it down in plain English. You might not know the subject. But it will no longer be an "unknown-unknown".

Second, who cares if you put in effort toward learning something and fail? Try again! It can take several iterations of learning on a single topic before you understand it. It took me at least three tries before I understood monads.

Finally, the very people we are afraid to admit our weaknesses to are the same people who can actually help us overcome these weakness. Better yet, they are often more than happy to do so! This involves getting over our primal fears of appearing inferior and being rejected by others. This is difficult but not impossible.

Conclusion

So remember the key lessons here. Focus a little bit at first. Don’t commit to learning more than 15 minutes a day, and pick a project with clear progress. Keep momentum going by working at something every day. Don't worry if a concept seems difficult. It's OK to take several tries at learning something. And above all, never be afraid to ask for help.

So what are you waiting for? If you've always wanted to learn Haskell but never have, download our Getting Started Checklist to start your journey!

Have you done a little Haskell, but still don't understand some functional programming concepts? Check out our free Recursion Workbook to learn about recursion, higher order functions, and try some practice problems!

Read More
James Bowen James Bowen

Interview with Doug Beardsley!

This week on Monday Morning Haskell, we have an exciting change of pace! I recently met with Doug Beardsley, a Haskell engineer at Takt. He was kind enough to agree to an interview with me. We discussed a number of topics, including learning Haskell, his work at Takt, and his view of the Haskell community as a whole.

You can find out more about him and his projects on his Github page. One of the more interesting things I saw there was his monad challenges repository. If you’ve read through the Monday Morning Haskell monad series and want some more hands on experience, I encourage you to try these challenges!

Perhaps the most striking response I heard from Doug was his answer about how welcoming and helpful the Haskell community is. Haskellers are always eager to answer newcomers’ questions! So if you haven’t written any Haskell yet, I encourage you to look through our Getting Started Checklist and take the first steps on your Haskell journey!

Without further ado, let’s get on to the interview!

Interview

Let’s start with some information about yourself. How long have been a software engineer? How long have you been using Haskell?

I started programming back in 1990ish, and I was pretty young. It wasn’t really software engineering level programming back then obviously, but I just immediately fell in love with it. I then learned C and programmed with it all through high school. And so I knew I wanted to be a computer science major in college. I went through that, graduated, started programming in the early 2000’s in industry, first in the defense industry for five/six years. Then I got a job programming Haskell. I moved to New York for that, and I’ve been doing Haskell pretty much full time ever since.

How long ago was that?

I started programming in Haskell professionally in 2010. I didn’t jump straight into Haskell professionally from zero. I think I started learning Haskell around 2006, maybe 2007.

So what Haskell concept was the hardest for you to learn?

Wow that’s a good question. I feel like with everything, there’s a spectrum. As you evolve, new things become harder. I definitely had a lot of trouble with monads early on. I feel like you don’t learn them at any one time. You just use them enough, and then you gradually build up a working knowledge of the tools and the APIs that are available around Control.Monad. I read through that so many times. If, like me, you don’t have a photographic memory, you just gotta keep going back through refreshing your memory, and eventually the patterns just kind of sink in.

I don’t know if I would say that was the hardest concept though. I feel like I can still use a much better understanding of say, profunctors, or some of the more obscure things that are going on in the lens package. But I don’t know. I kinda don’t like questions like “What is the superlative of something”, because it depends on the day really.

That makes sense. What advice would you have for someone who has tried to learn Haskell and has either given up, or is having a really tough time? Are there any 80/20 ideas or important easy wins when learning Haskell?

The biggest thing for me is you need to have intrinsic motivation. So in my case, I had an app that I wanted to build, and I had been building it in Drupal, with PHP, and that just fell flat on its face very quickly. I really wanted to build the app, for myself, not for a startup or to make money; I wanted it for myself. So I had a very high level of intrinsic motivation.

I wasn’t really a big fan of web programming back then, I was more of a back-end kind of programmer, and I thought “I want to learn a new language, Haskell seems like one of the more challenging ones that would stretch me more, maybe it’ll make web programming interesting”. As someone once said on IRC, “a spoonful of Haskell makes the web programming go down”. Which I think is a very apt description of my case, so I just dove in. I started working on it. It was a way bigger project than I should have been working on as a Haskell novice.

But I think that was good. You need to be working on something you think is maybe a little bit beyond you. And if you also have that intrinsic motivation taken care of, then it almost solves itself. You’re going to bang your head against a wall until you beat it. I’ve heard a friend of mine is really big into natural language learning and says you just have to find some way of getting over this incredible hurdle because it’s so hard. You just have to make yourself do it. For Haskell I think it’s a very similarly challenging endeavor, and you really have to have intrinsic motivation.

So the WHY is almost more important than any particular WHAT?

Yea I think so. I just started out with Project Euler problems, which is something I hear a lot of people do. And OK great, it’s like “Oh, I’ll spend some time working on this problem.” You spend an hour on it, and you don’t learn a whole lot of Haskell. You learn a little bit of the basic syntax, but not a lot that’s useful in terms of real world development. And there’s not a whole lot of intrinsic motivation there. I suppose maybe you could say, “Oh I want to finish all the problems.” But that’s not really a question of learning Haskell. That’s more a question of learning math than any particular programming language.

And so I think you need a project that’s going to push you into a fair number of realistic, real world situations. In my case, a web app was suitable. Web apps do pretty well because they involve a fair number of pieces of technology and teach you the software development process. But yea, it’s not so much the “what”, for sure. It’s just, you gotta have a reason that lights a fire under you.

I guess my own experience is a little bit like that. I had this product idea and I had done simple versions of a couple of the pieces of that idea in college in a class where I first learned Haskell. And I thought, well I could just use Haskell for this whole project. So then I put the whole project together and that’s what started getting me towards learning the more practical side of things like Stack. It also got me to learn more about monads and that sort of stuff.

So having worked on Haskell in industry, what is your take on the idea widely held in many parts of the programming community that Haskell isn’t suitable for production use? Obviously you’re very opinionated here.

Yea it just couldn’t be farther from the truth. There are plenty of people in the world who are doing production stuff in Haskell and I think that proves it. For instance, JanRain, I think, has used Snap [a Haskell library] for years. I assume they still are, but I used to be able to say “hey, when you go to ladygaga.com, you’re hitting a snap server”. And that’s real stuff. That’s solving real problems in the real world.

We don’t have yet the Google or the Facebook or something of that scale. Though Facebook actually is using Haskell (on the side), just not with their forward user facing stuff. So we don’t have a huge example to point at, but there’s certainly people using Haskell every day in production. So it’s just straight up not true that it can’t be done.

So what is the biggest challenge you’ve had using Haskell on an industry project?

There’s a couple of things that jump out. One was a some kind of machine learning or more numerical algorithm I was working on. It might’ve been a hidden markov model or something with a lot of math going on. And I had a fair amount of trouble getting that right. This was quite a while back, so I was less experienced than I am now.

I think part of the challenge there was not having the right abstractions for multi-dimensional matrix math. And I think Haskell is still not really in a fantastic state there. You can do it, you can accomplish the matrix math with say, HMatrix, and I was able to. But in terms of wrangling dimensions and units and stuff like that, I probably didn’t know to take advantage of some of the things that are available now.

There were definitely some challenges there and it seemed like a very difficult thing to get right. Although I suspect it’s difficult to get right no matter what language you’re using. So it may be the case that Haskell just doesn’t have as much of an advantage there until we get some really phenomenal matrix libraries that could help us solve that problem a lot more nicely.

Another situation where I had frustrations was with an ETL [Extract-Transform-Load == migrating a legacy system] that I was working on and it was so miserable to get right. I was just doing it the naive way bashing through the problem head-on using the IO monad. I was trying to abstract things just using functions, type classes, and whatever other functional techniques I knew about.

Maybe what I should have done is gone back and looked at some kind of a more fundamental approach, perhaps an EDSL [Embedded Domain Specific Language] with say, a GADT [Generalized Algebraic Data Type] and specifying operations representing the structure of what I was trying to do. Then I would have an interpreter that would interpret that in a test type of context where I might be counting different operations that are happening in all manner of checks that you might want to do. Then I would have another interpreter that interprets it in IO and you can kind of test these things in a more structured way.

I think there were a lot of things I could have done better in that project, but maybe as happens in so many projects, there was time pressure. And if that’s the background situation, then you’re less likely to take your time and look for a really good solution to that problem.

Like you said, there’s often a brute-force solution and then a more elegant solution in most software projects. But if you’re operating under major time pressures like so many projects are, it’s hard to find it, especially in Haskell.

I feel like if I had maybe had prior experience with using some of those more elegant solutions, I would have been more likely to jump to them. And this is maybe an obstacle in a more general way. Learning to find a reason to use some of these things, so then you’ll be able to use them in the real world.

Yea that’s a very interesting problem.

To what extent do you think abstract math is necessary to understand Haskell, and to what extent do you think it is helpful? Is there a particular instance where you’ve used higher math to solve a Haskell problem?

I don’t think it is necessary at all to be productive with Haskell. I wouldn’t consider myself super strong in category theory. I took an abstract algebra class in college, so I’m not at the bottom of the barrel, but I don’t think it was super significant to learning Haskell. Things definitely come up. You’ve got all kinds of examples of places where people have leveraged abstract math. But I feel like the knowledge of those structures might actually be part of the answer to the problem we were talking about a second ago.

If you are adequately motivated and you know about this structure somehow, you can use it. The Lens library comes to mind as one. You may not know how profunctors or prisms or whatever other concepts there are, but you know about the lens library, so you can learn about concepts that way, in a library/problem directed way. Maybe knowing the structures would help you know what to use for a more elegant solution to a problem.

But at the same time, when I have studied some category theory concepts, it’s not obvious at all how I’m going to apply them to programming, so we need to do much better as a community at bridging this gap between theory and practice. I think we already do better than any community out there though. Which is good because Haskell does have this reputation of being a very theoretical language. I think we do a great job, but I think we can still improve a lot.

Yea I’m wondering...is there even a theoretical PHP for that community to bridge?

Yea maybe that’s an oxy-moron...

What’s your favorite miscellaneous Haskell library?

Boy, that’s an interesting question. One thing that pops to mind is libraries that represent paths more semantically. So you can concatenate them and manipulate them without having to parse and split on slashes and things like that. I feel like I should have an answer to this question.

Perhaps it’s just far enough back in my brain that I’m not thinking of it right now. But yea, paths are something I encountered a while back. When you really need it, they’re a really cool thing to have...being able to target absolute paths and relative paths. There’s perhaps a whole algebra of paths there that some libraries can give you which is interesting.

What is your least favorite thing about Haskell?

I would say it’s the fact that sometimes we DON’T have referential transparency. The thing that comes to mind that I’ve encountered just recently was that I wanted to just make something generic over a particular prism but I couldn’t, because each of the prisms I would have ended up using returned a different value. So it needed to be more monomorphic than I would have ideally wanted.

So instead of having the absolute right level of abstraction, I had to add a level of repetition to get an Int64 or whatever I was prism-ing out to. We do have referential transparency but occasionally there’s some of these real-world type system restrictions that force us to be more monomorphic than we would like.

So let’s talk a little bit about Takt, where you work. I guess first, do you want to give a quick elevator pitch about Takt? What do you do, what problems do you solve, both the company as a whole, and you yourself?

The company as a whole has lots of very interesting problems. We’re a fairly large-scale data processing/data-science company automating for clients and making intelligent decisions to the point of trying to create a more personalized experience for our clients’ customers. There’s tons of interesting problems to solve there. The one that I’ve been working on most recently is just building a web front-end. And so we’re using Haskell and GHCJS and the Reflex FRP library to build UIs that are robust and easy to refactor and be confident about. So that’s my area of focus.

The company is just a fantastic place to work. It’s really refreshing to have a group of people who are unified in the pursuit of Haskell as the right solution to many of our problems. There are some cases where maybe it’s not the right solution. Maybe you just need some quick and dirty scripts on a server. Especially if you don’t have GHC on that server. So there’s plenty of real world situations where you end up reaching for something else. But as often as we can we like to reach for Haskell, and that’s a really fun environment to be involved in.

In what ways do you think Haskell is uniquely suited for solving Takt’s problems?

I feel that Haskell is uniquely suited for solving ALL the world’s software problems! I truly believe that Haskell or at least the ideas that Haskell is based on are the future of software. The future of more reliable, robust software. And so I feel like it’s going to the future for all of Takt’s software problems.

What is one piece of advice for someone you might have for someone who might want to apply to Takt?

Well if you’re not a Haskell programmer, you should learn some Haskell for sure. I even wrote a blog post awhile back about how to get a Haskell job. You can’t really expect people to hire you for a language that is as different from the mainstream as Haskell is without some prior experience. You can’t expect a company to hire you as any kind of programmer without having some prior experience programming. So I think that’s a pretty natural thing. It’s maybe frustrating for some people who have trouble finding the time to invest in learning Haskell, but it’s kind of a reality.

For Haskell programmers out there who are interested in working at Takt, talk to us! We’d love to hear from you. If you don’t want to just put your resume on a faceless website, you can contact me and open a conversation that way. It’s really nice when candidates have public work that we can look at and get an idea of what kind of Haskell skills you have. We don’t require that because there are plenty of candidates out there that don’t have that for whatever reason, but it can’t hurt.

We’re in the business of trying to reduce risk, and the more we can know about you, the better. Open source contributions are really helpful there. And the more visible that particular project is, the more it’s going to be significant in making us take a look at you and make us excited to talk to you.

Awesome. So let’s finish up with a couple questions about the broader community. What’s your take on the Haskell community at large? What are its strengths, weaknesses, etc..

I think we’re super strong in the area of just being willing to help newcomers. Super friendly. I can’t possibly count how many hours I’ve spent getting help online from people who were just giving me their time just to help me learn some abstract concept where I was taking forever to catch on. It’s just a fantastically friendly and talented community.

I’ve had the opportunity to look at jobs where we were advertised in both a Haskell forum and a non-Haskell forum and the Haskell candidates were just an order of magnitude better and more promising. Now I can’t say that proves anything, because maybe there were other differences about the way those two postings were done that would bias it somehow. But it seems to suggest that it’s a phenomenal filter. If you’re involved in the Haskell community, then you have a lot of intrinsic motivation like we talked about earlier.

You just can’t get to a working knowledge of Haskell by sitting around, being lazy, and watching TV. You gotta actually work for it. Anything in life that requires people to really work for it is going to be a strong predictor of success or maybe the ability to be successful, or a lot of attributes that are aligned and I think are valuable in potential employees.

Very interesting. What changes do you see happening in the Haskell community or the language itself in the next year?

Hmmm that’s a good question. Well I hope to be able to say in the next year or two that Takt is contributing some new libraries and new points in the ecosystem that are missing. Hopefully we can get some more companies using Haskell for adoption. I think there’s some more work recently to make Haskell more tractable for newcomers, and I think that’s fantastic. That’s an area where we’ve struggled a little bit because we are so different from the mainstream. And I really look forward to seeing things grow.

Awesome! That’s all the questions I have. Thanks so much for doing this interview.

It’s a pleasure!

Wrap Up

Hopefully our interview helped give you a better idea of what it’s like working with Haskell in industry. And as Doug mentioned, the Haskell community is very welcoming to newcomers! If you’ve never tried Haskell before, check out our Getting Started Checklist. It’ll show you what tools you need to start writing your first lines of Haskell.

If you’ve done a little Haskell already but want some more practice, you should try our free Recursion Workbook. It has lots of material on recursion and also includes 10 practice problems!

Be sure to check out the Monday Morning Haskell Blog next week. We’ll have a new piece on how we can use Haskell compiled nature to help drive our development and improve our productivity!

Read More
James Bowen James Bowen

Easing Haskell's Intimidating Glare

All of my previous articles have discussed basic language features and concepts in Haskell. My hope has been to provide new Haskellers with suitable starting material to help them get started. Even just as a language, Haskell is complex. There are many technical challenges and paradigm shifts one has to overcome to learn it. This is especially true for those coming from imperative languages.

However, this article will focus on something equally important. It’s no secret that most people consider Haskell not just a difficult language to learn technically, but an intimidating language. It has undoubted psychological hurdles. People seem to give up on Haskell at a higher rate than most other languages. By naming these problems, we can overcome them.

An Academic Language

People have long considered Haskell primarily as a research language. It builds on the lambda calculus, possibly the simplest, purest programming language. This gives it a host of connections to cool concepts in abstract mathematics, primarily the province of professors and PhD. students. The connection is so elegant many mathematical ideas can be well represented in Haskell.

But this connection has a price in accessibility. Important Haskell concepts include functors, monads, categories, etc. These are cool, but few without a math degree have any intuition for what the terms mean. Compare these to terms from other languages: class, iterator, loop, template. These terms are a lot more intuitive, so the languages using them have an automatic advantage in accessibility.

Aside from this terminology point though, the great academic interest is a good thing, not a bad thing. However, on the production side of things, the tooling has not been sufficient. It was simply too difficult to maintain a large-scale Haskell project. As a result, companies had little incentive to use it. This meant there was little to no balance of the academic influence.

Knowledge Distribution

The net result of Haskell’s academic primacy is a skewed knowledge base. The nature of academia is relatively few people spend a large amount of time on a relatively small set of problems. Consider another academic field, like virology. You have some experts who understand viruses at an extremely high level, and the rest of us know quite little. There are no hobbyist virologists. Unfortunately, this kind of distribution is not conducive to introducing new people to a topic.

Naturally, people have to learn from those who know more than they do. But the truth is they don’t want their teachers to be too much better. It helps tremendously to learn from someone who was in your shoes not too long ago. They’ll more likely remember the pitfalls and frustrations they encountered early on, so they’ll be able to help you avoid them. But when the distribution skews towards the extreme, there is no middle class. There are fewer people who can optimally teach new learners. In addition to not remembering old mistakes, experts tend to use overly complicated terminology. New folks may feel intimidated by this and despair.

Turning the Tide of Production

The lack of production work mentioned above contributes substantially to this divide. Many other languages, like C++, have strong academic followings. But since so many companies use C++ in production, it does not face the knowledge distribution problem Haskell does. Companies using C++ have no choice but to train people to use the language. Many of these people stick with the language long enough to train the next generation. This creates a more normal looking knowledge distribution curve.

The good news for Haskell is there have been major tooling improvements in the last few years. This has brought about a renaissance for the language. More companies are starting to use it in production. More meetups are happening; more people are writing libraries for the most crucial tasks. If this trend continues, Haskell will hopefully reach a tipping point, normalizing the knowledge distribution curve.

The Key Insight

If you are someone who is interested in learning Haskell, or who has tried learning Haskell in the past, there is one key thing to know. While the abstract mathematics is cool, understanding it is mostly unnecessary. Monads are essential, there is no denying. But category theory is overkill for most day-to-day problems you’ll solve. The dozens of language extensions might seem intimidating, but you can pick them up one-by-one as you go.

At the last Haskell eXchange, Don Stewart from Standard Chartered gave a talk about the company’s use of Haskell. He explained they rarely use anything outside of vanilla Haskell constructs*. They just don’t need to. Anything you can do with, say, lenses, you can accomplish without them.

Haskell is different from most other programming languages. It constrains you in ways those languages do not. But the constraints are not nearly as binding as they seem. You can’t use for loops. So use recursion. You can’t re-assign variables. So create new names for expressions. You just have take it one step at a time.

Taking Action

If this has inspired you to get started with Haskell, check out this checklist to learn the tools you need to get started.

If you’re already familiar with the basics and want to take the next step up, you should take a look at our workbook. You’ll learn about recursion and get to take a shot at 10 practice problems to test your skills!

Note

*At least with respect to their normal Haskell code. Some of their code is in a proprietary language of theirs called Mu, which is built on Haskell but obviously different.

Read More